題解 CF493E 【Vasya and Polynomial】
題意簡述
給定正整數 \(t,a,b\),求滿足 \(P(t)=a,P(a)=b\) 的非負整係數多項式 \(P(x)\) 的個數。
題目分析
顯然 \(P(x) \geq x\),故必須滿足 \(t \leq a \leq b\) ,否則無解。
設 \(P(x)=p_0+p_1x+p_2x^2+ \dots +p_nx^n\)。
首先有一個很重要的性質:每個係數都小於等於 \(a\),即 \(p_i \leq a\)。
- 若存在 \(p_i>a\) ,\(P(t) \geq p_it^i \geq p_i > a\),矛盾。
由上面的證明可以知道當存在 \(p_i=a\)
存在 \(p_i=a\)
此時多項式只有一項,故 \(i=n\) 。
- 若 \(n=0,P(x)=a\)。
將 \(a\) 代入得 \(P(a)=a\) ,故 \(P(x)\) 存在當且僅當 \(a=b\)。
- 若 \(n>1,P(x)=p_nx^n\)。
將 \(t\) 代入得 \(P(t)=at^n=a\) ,得 \(t^n=1\) ,故 \(t=1\) 。
將 \(a\) 代入得 \(P(a)=a^{n+1}=b\) 。
故 \(P(x)\) 存在當且僅當 \(t=1\) 且 \(a^{n+1}=b\) 。
注意 \(a=1\) 時只有可能無解或無窮解:
-
\(b=1\) 時,有無窮解。
-
\(b>1\) 時,無解。
\(a>1\) 時直接暴力列舉 \(n\) 即可,至多為 \(log_2(10^{18})\)。
所有 \(p_i<a\)
將 \(b\) 表示成 \(a\) 進位制,就可以構造出一個 \(P(a)=b\) ,並且至多隻有一個。
以下是證明,不過簡單來說,就是將 \(b\) 表示成 \(a\) 進位制的形式是唯一的。
\(P(a)=p_0+p_1a+p_2a^2+ \dots +p_na^n=b\)
假設存在另一個 \(P'(a)=b\)
\(P'(a)=p_0'+p_1'a+p_2'a^2+ \dots +p_n'a^n=b\)
兩式相減
\((p_1-p_1')a+(p_2-p_2')a^2+ \dots +(p_n-p_n')a^n=0\)
因為 \(P(x) \neq P'(x)\) ,存在 \(m\) 使 \(p_m-p_m' \neq 0\) ,令 \(m\) 取最大值(也就是最高次數的不為0的項)。
\((p_1-p_1')a+(p_2-p_2')a^2+ \dots +(p_m-p_m')a^m=0\)
\(|(p_1-p_1')a+(p_2-p_2')a^2+ \dots +(p_m-p_m')a^m|=|(p_m-p_m')a^m| (*)\)
又因為 \(0 \leq p_i,p_i' \leq a-1\) ,故 \(|p_i-p_i'| < a\)。
\(|(p_1-p_1')a|<a^2\)
\(|(p_1-p_1')a+(p_2-p_2')a^2<a^2+a^2(a-1)|=a^3\)
\(|(p_1-p_1')a+(p_2-p_2')a^2+(p_3-p_3')a^3<a^3+a^3(a-1)|=a^4\)
以此類推,故 \(|(p_1-p_1')a+(p_2-p_2')a^2+ \dots +(p_{m-1}-p_{m-1}')a^{m-1}|<a^m\)
而 \(|(p_m-p_m')a^m|>=a^m\)
與 \((*)\) 矛盾。
上面那一堆東西簡單來說,就是將 \(b\) 表示成 \(a\) 進位制的形式是唯一的。
求出 \(P(x)\) ,再將 \(t\) 代入檢驗一下 \(P(t)=a\) 就行了。
程式碼
#include<bits/stdc++.h>
using namespace std;
long long T,t,a,b;
long long cnt,tot;
long long ans[65];
bool check(long long x,long long y){//檢驗P(t)=a
long long tot=0;
long long k=1;
for(long long i=0;i<=cnt;i++){
tot+=k*ans[i];
k*=x;
if(tot>y) return false;
}
return (tot==y);
}
long long cal(long long a,long long b){//計算a^k=b
long long cn=0;
while(b%a==0){
cn++;
b/=a;
}
if(b!=1) return -1;
return cn;
}
int main(){
scanf("%lld%lld%lld",&t,&a,&b);
if(t==1 && a==1 && b==1){//特判無數解
printf("inf");
return 0;
}
if(a==b) tot++;//p_i=a,n=0
if(t==1 && a>1){//p_i=a,n>0
long long tmp=cal(a,b);
if(tmp!=-1 && tmp>1) tot++;
}
if(a>1){//p_i<a
cnt=-1;
long long tmp=b;
while(tmp) ans[++cnt]=tmp%a,tmp/=a;
if(check(t,a)) tot++;
}
printf("%lld",tot);
}