題目連接:php
BZOJ2742測試
好想吐槽某谷評分制度。。爲何我評個藍以後從紫變成了黑。。。spa
首先,設解$x=\frac{p}{q}(Gcd(p,q)=1)$code
那麼就有$\sum_{i=0}^n\limits a_ix^i=0$ip
$\sum_{i=0}^n\limits a_i(\frac{p}{q})^i=0$get
乘以$q_i$通分:$\sum_{i=0}^n\limits a_ip^iq^{n-i}=0$it
那麼能夠推導出:io
$\sum_{i=0}^n\limits a_ip^iq^{n-i}\equiv a_0q^n\equiv 0(mod\ p)$Mark
class
$\sum_{i=0}^n\limits a_ip^iq^{n-i}\equiv a_np^n\equiv 0(mod\ q)$
由於$p,q$互質那麼獲得結論:$p|a_0,q|a_n$
暴力枚舉$p,q$代入方程判斷合法便可。
如何判斷?能夠選取一個模數看兩邊在同餘系下是否相同(詳情能夠參考Luogu2312解方程)
不放心能夠多選幾個進行測試。
還有幾個須要注意的問題:
$a_0=0$怎麼辦?怎麼枚舉$p$?
找到一個最小的$i$使得$x_i\not=0$,那麼枚舉$x_i$的因子便可(此時上文推導Mark處的$mod\ p$就變成了$mod\ p^{i+1}$)
第二是要判斷負數解,即$-\frac{p}{q}$
最後須要特判最終解$x=\frac{p}{q}=0$的狀況(即$a_0=0$)。
時間複雜度:能過
代碼:
#include <cstdio> #include <vector> #include <algorithm> typedef long long ll; inline int Abs(const int x){return x>=0?x:-x;} int Gcd(const int a,const int b){return b?Gcd(b,a%b):a;} ll Pow(ll a,ll b,const int p) { ll Res=1; for(;b;b>>=1,a=a*a%p) if(b&1)Res=Res*a%p; return Res%p; } int n,a[105]; const int Mod=1000000007; struct Fraction { int p,q; inline bool operator<(const Fraction &o)const {return (double)p/q<(double)o.p/o.q;}//分數 p爲分子 q爲分母 }; std::vector<int> Factor[2];//a[0](a[i])和a[n]的因子 std::vector<Fraction> Answer; void Get_Factor(const int Number,std::vector<int> &Result)//求Number的因子,存放在Result中 {for(int i=1;i<=Number;++i)if(Number%i==0)Result.push_back(i);}//O(N)遍歷已經足夠 void Check_Answer(int p,int q)//判斷解可行性 { ll g=Gcd(Abs(p),Abs(q)),xs=1,Value=0,x=p*Pow(q,Mod-2,Mod)%Mod; if(g>1)return;//防止解重複,如1/2,2/4,3/6... for(int i=0;i<=n;++i) { Value=(Value+a[i]*xs)%Mod; xs=xs*x%Mod; } if(!Value)Answer.push_back((Fraction){p,q}); } int main() { scanf("%d",&n); for(int i=0;i<=n;++i)scanf("%d",&a[i]); for(int i=0;i<=n;++i) if(a[i]!=0)Get_Factor(Abs(a[i]),Factor[0]),i=n; Get_Factor(Abs(a[n]),Factor[1]); if(!a[0])Answer.push_back((Fraction){0,1}); for(int i=0;i<(int)Factor[0].size();++i) for(int j=0;j<(int)Factor[1].size();++j) { Check_Answer(+Factor[0][i],Factor[1][j]); Check_Answer(-Factor[0][i],Factor[1][j]); } std::sort(Answer.begin(),Answer.end()); printf("%d\n",(int)Answer.size());//按要求輸出解 for(int i=0;i<(int)Answer.size();++i) if(Answer[i].q==1)printf("%d\n",Answer[i].p); else printf("%d/%d\n",Answer[i].p,Answer[i].q); return 0; }