题目链接:
好想吐槽某谷评分制度。。为什么我评个蓝之后从紫变成了黑。。。
首先,设解(x=frac{p}{q}(Gcd(p,q)=1))
那么就有(sum_{i=0}^nlimits a_ix^i=0)
(sum_{i=0}^nlimits a_i(frac{p}{q})^i=0)
乘以(q_i)通分:(sum_{i=0}^nlimits a_ip^iq^{n-i}=0)
那么可以推导出:
(sum_{i=0}^nlimits a_ip^iq^{n-i}equiv a_0q^nequiv 0(mod p))Mark
(sum_{i=0}^nlimits a_ip^iq^{n-i}equiv a_np^nequiv 0(mod q))
因为(p,q)互质那么得到结论:(p|a_0,q|a_n)
暴力枚举(p,q)代入方程判断合法即可。
如何判断?可以选取一个模数看两边在同余系下是否相同(详情可以参考Luogu2312解方程)
不放心可以多选几个进行测试。
还有几个需要注意的问题:
(a_0=0)怎么办?怎么枚举(p)?
找到一个最小的(i)使得(x_i ot=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
",(int)Answer.size());//按要求输出解
for(int i=0;i<(int)Answer.size();++i)
if(Answer[i].q==1)printf("%d
",Answer[i].p);
else printf("%d/%d
",Answer[i].p,Answer[i].q);
return 0;
}