BZOJ 2742: [HEOI2012]Akai的数学作业
2742: [HEOI2012]Akai的数学作业
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 572 Solved: 236
[Submit][Status][Discuss]
Description
这里是广袤无垠的宇宙这里是一泻千里的银河
这里是独一无二的太阳系
这里是蔚蓝色的地球
这里,就是这里,是富饶的中国大陆!
这里是神奇的河北大地
这里是美丽的唐山
这里是神话般的唐山一中
这里是Akai曾经的教室
黑板上还留有当年Akai做过的数学作业,其实也并不是什么很困难的题目:
“
给出一个一元n次方程:
a0 + a1x + a 2 x2 +…+ anxn= 0
求此方程的所有有理数解。
” Akai至今还深刻记得当年熬夜奋战求解的时光
他甚至还能记得浪费了多少草稿纸
但是却怎么也想不起来最后的答案是多少了
你能帮助他么?
Input
第一行一个整数n。第二行n+1个整数,分别代表a 0 到a n
Output
第一行输出一个整数t,表示有理数解的个数
接下来t行,每行表示一个解
解以分数的形式输出,要求分子和分母互质,且分母必须是正整数特殊的,如果这个解是一个整数,那么直接把这个数输出
等价的解只需要输出一次
所有解按照从小到大的顺序输出
Sample Input
3
-24 14 29 6
-24 14 29 6
Sample Output
3
-4
-3/2
2/3
-4
-3/2
2/3
HINT
【数据范围】
对于30%的数据,n<=10
对于100%的数据,n <= 100,|a i| <= 2*10^7,an≠ 0
Source
分析:
对于一个多项式我们可以把它写成$f(x)=\prod (b_{i}x+c_{i})$的形式,每一个一次多项式都有一个复数域下的根,这道题求的是有理数解,所以可以写成$f(x)=g(x) \prod (b_{i}x+c_{i})$的形式,其中$g(x)$包含了所有含非有理数解的一次多项式,那么所有的解就是$x=-\frac {c_{i}}{b_{i}}$,我们观察发现,所有的$c_{i}$的乘积一定被包含在$a_0$,所有的$b_{i}$的乘积一定被包含在$a_n$,所以我们枚举$a_0$和$a_n$的约数,然后代入方程判断...
注意有$a_0=0$的情况...这个时候就把多项式整体往前挪...
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
//by NeighThorn
using namespace std;
const int maxn=100+5,maxm=500000+5,mod=1e9+7;
int n,tot,a[maxn],p[maxn],q[maxn],fac[2][maxm],cnt[2];
struct M{
int x,y;
friend bool operator < (M a,M b){
return (double)a.x/(double)a.y<(double)b.x/(double)b.y;
}
}ans[maxm];
inline int power(long long x,int y){
long long res=1;
while(y){
if(y&1)
res=res*x%mod;
x=x*x%mod,y>>=1;
}
return res;
}
inline bool check(int x,int y){
long long ans=0;
for(int i=0;i<=n;i++)
(ans+=1LL*a[i]*power(x,i)%mod*power(y,n-i)%mod)%=mod;
if(ans)
return 1;
return 0;
}
inline int gcd(int x,int y){
return y==0?x:gcd(y,x%y);
}
signed main(void){
scanf("%d",&n);
for(int i=0;i<=n;i++)
scanf("%d",&a[i]);
int lala=0;
while(a[lala]==0)
lala++;
if(lala!=0){
for(int i=0,j=lala;j<=n;i++,j++)
a[i]=a[j];
n-=lala;
ans[++tot].x=0,ans[tot].y=1;
}
if(n==0){
puts("0");
return 0;
}
int xx=abs(a[0]),yy=abs(a[n]),x=sqrt(xx),y=sqrt(yy);
for(int i=1;i<=x;i++)
if(xx%i==0){
fac[0][++cnt[0]]=i;
if(i*i<=xx&&xx/i!=i)
fac[0][++cnt[0]]=xx/i;
}
for(int i=1;i<=y;i++)
if(yy%i==0){
fac[1][++cnt[1]]=i;
if(i*i<=yy&&yy/i!=i)
fac[1][++cnt[1]]=yy/i;
}
for(int i=1;i<=cnt[0];i++)
for(int j=1;j<=cnt[1];j++){
if(gcd(fac[0][i],fac[1][j])==1){
if(!check(fac[0][i],fac[1][j]))
ans[++tot].x=fac[0][i],ans[tot].y=fac[1][j];
if(!check(-fac[0][i],fac[1][j]))
ans[++tot].x=-fac[0][i],ans[tot].y=fac[1][j];
}
}
sort(ans+1,ans+tot+1);printf("%d\n",tot);
for(int i=1;i<=tot;i++){
if(ans[i].y!=1)
printf("%d/%d\n",ans[i].x,ans[i].y);
else
printf("%d\n",ans[i].x);
}
return 0;
}
By NeighThorn

浙公网安备 33010602011771号