2742: [HEOI2012]Akai的数学作业
Time Limit: 10 Sec
Memory Limit: 128 MB
Submit: 510
Solved: 213
[ 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
[ Submit][ Status][ Discuss]
数学功底太差啦。。不会做= =
最后,暴力分解an,a0的质因子,枚举判断就行了。数值太大就取模。。
如果a0 == 0?两边同时除以x^k,让最小的ai != 0变成a0就行了,特判此时有一根0
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int maxn = 5050;
const int N = 111;
const int T = 5;
const LL mo[5] = {299979457,299960249,299941561,299922113,299902541};
struct data{
int A,B,typ; data(){}
data(int A,int B,int typ):
A(A),B(B),typ(typ){}
bool operator != (const data &b) const
{
return A != b.A || B != b.B || typ != b.typ;
}
bool operator < (const data &b) const
{
if (typ < b.typ) return 1;
if (typ > b.typ) return 0;
if (typ > 0) return 1LL*A*b.B < 1LL*B*b.A;
else return 1LL*A*b.B > 1LL*B*b.A;
}
}Ans[10000000];
int n,ta,tb,tot,cur = 1,a[N],A[maxn],B[maxn];
LL mq[N][5],mp[N][5];
int gcd(const int &x,const int &y) {return !y?x:gcd(y,x%y);}
void Mul(LL *C,LL *D,LL k)
{
for (int i = 0; i < T; i++)
D[i] = C[i]*k%mo[i];
}
void Add(int *C,LL *x,LL *y,LL k)
{
for (int i = 0; i < T; i++)
C[i] += x[i]*y[i]%mo[i]*k%mo[i],C[i] = (C[i] + mo[i]) % mo[i];
}
void Dec(int *C,LL *x,LL *y,LL k)
{
for (int i = 0; i < T; i++)
C[i] -= x[i]*y[i]%mo[i]*k%mo[i],C[i] = (C[i] + mo[i]) % mo[i];
}
void Work(int Num,int &tt,int *C)
{
int sqr = sqrt(Num);
for (int i = 1; i <= sqr; i++)
if (Num % i == 0)
{
C[++tt] = i;
C[++tt] = Num / i;
}
if (sqr*sqr == Num) C[tt--] = 0;
}
void Judge(int q,int p)
{
int g = gcd(q,p); q /= g; p /= g;
int G[2][T]; memset(G,0,sizeof(G));
for (int i = 1; i <= n; i++)
{
Mul(mq[i-1],mq[i],q),Mul(mp[i-1],mp[i],p);
//for (int j = 0; j < T; j++) printf("%d ",mq[i][j]); cout << endl;
//for (int j = 0; j < T; j++) printf("%d ",mp[i][j]); cout << endl;
}
for (int i = 0; i <= n; i++)
{
Add(G[0],mp[n-i],mq[i],a[i]);
if (i&1) Dec(G[1],mp[n-i],mq[i],a[i]);
else Add(G[1],mp[n-i],mq[i],a[i]);
//for (int j = 0; j < T; j++) printf("%d ",G[0][j]); cout << endl;
//for (int j = 0; j < T; j++) printf("%d ",G[1][j]); cout << endl;
}
bool flag0,flag1; flag0 = flag1 = 1;
for (int i = 0; i < T; i++)
{
if (G[0][i] != 0) flag0 = 0;
if (G[1][i] != 0) flag1 = 0;
}
if (flag0) Ans[++tot] = data(q,p,1);
if (flag1) Ans[++tot] = data(q,p,-1);
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n; int pos = 0;
for (int i = 0; i <= n; i++) scanf("%d",&a[i]);
while (!a[pos]) ++pos;
if (pos)
{
Ans[++tot] = data(0,1,1); n -= pos;
for (int i = 0; i <= n; i++) a[i] = a[i+pos];
}
Work(abs(a[0]),ta,A); Work(abs(a[n]),tb,B);
//cout << ta << endl; for (int i = 1; i <= ta; i++) printf("%d ",A[i]); cout << endl;
//cout << tb << endl; for (int i = 1; i <= tb; i++) printf("%d ",B[i]); cout << endl;
for (int i = 0; i < T; i++) mq[0][i] = mp[0][i] = 1;
for (int i = 1; i <= ta; i++)
for (int j = 1; j <= tb; j++)
Judge(A[i],B[j]);
sort(Ans + 1,Ans + tot + 1);
for (int i = 2; i <= tot; i++)
if (Ans[i] != Ans[i-1]) Ans[++cur] = Ans[i];
cout << cur << endl;
for (int i = 1; i <= cur; i++)
{
if (Ans[i].typ == -1) putchar('-');
if (Ans[i].B == 1) printf("%d\n",Ans[i].A);
else printf("%d/%d\n",Ans[i].A,Ans[i].B);
}
return 0;
}