BZOJ 2742: [HEOI2012]Akai的数学作业

2742: [HEOI2012]Akai的数学作业

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

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

posted @ 2017-03-02 19:30  NeighThorn  阅读(247)  评论(0编辑  收藏  举报