[NOIP2014] 提高组 洛谷P2312 解方程
题目描述
已知多项式方程:
a0+a1x+a2x^2+..+anx^n=0
求这个方程在[1, m ] 内的整数解(n 和m 均为正整数)
输入输出格式
输入格式:
输入文件名为equation .in。
输入共n + 2 行。
第一行包含2 个整数n 、m ,每两个整数之间用一个空格隔开。
接下来的n+1 行每行包含一个整数,依次为a0,a1,a2..an
输出格式:
输出文件名为equation .out 。
第一行输出方程在[1, m ] 内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m ] 内的一个整数解。
输入输出样例
输入样例#1:
2 10 1 -2 1
输出样例#1:
1 1
输入样例#2:
2 10 2 -3 1
输出样例#2:
2 1 2
输入样例#3:
2 10 1 3 2
输出样例#3:
0
说明
30%:0<n<=2,|ai|<=100,an!=0,m<100
50%:0<n<=100,|ai|<=10^100,an!=0,m<100
70%:0<n<=100,|ai|<=10^10000,an!=0,m<10000
100%:0<n<=100,|ai|<=10^10000,an!=0,m<1000000
直接计算无疑是不可能做到的。
将每一项的系数都模一个质数,若一个数是方程的解,那么在模的意义下它也是方程的解(但反过来不一定)。
为了解决这个“不一定”的问题,多选几个质数,若一个数在不同模的意义下都是方程的解,那么它有极大的几率就是原方程的解了。
↑如果素数选得不好,这题还是会WA。
↑所以这是道拼RP的题。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mod[8]={0,13,7901,3947,131,6977,22877,49997}; 10 char s[105][1000010]; 11 int n,m; 12 int num[9][120]; 13 bool solve(int od,int x){ 14 int i,j; 15 long long tmp=0; 16 long long pw=1; 17 for(i=0;i<=n;++i){ 18 // printf("%d %d\n",num[od][i],pw); 19 if(s[i][0]=='-') tmp=(tmp-pw*num[od][i])%mod[od]; 20 else tmp=(tmp+pw*num[od][i])%mod[od]; 21 pw=pw*x%mod[od]; 22 } 23 while(tmp<0) tmp+=mod[od]; 24 if(!tmp)return true; 25 return false; 26 } 27 int res[1000010]; 28 int ans[1000010],act=0; 29 int main(){ 30 int i,j,k; 31 scanf("%d%d",&n,&m); 32 for(i=0;i<=n;++i) 33 scanf("%s",s[i]); 34 int len[101]; 35 for(i=0;i<=n;++i)len[i]=strlen(s[i]); 36 for(k=1;k<=7;++k) 37 for(i=0;i<=n;++i){ 38 for(j=0;j<len[i];++j){ 39 if(s[i][j]=='-')continue; 40 num[k][i]=num[k][i]*10+s[i][j]-'0'; 41 num[k][i]%=mod[k]; 42 } 43 } 44 for(k=1;k<=7;++k) 45 for(i=0;i<mod[k] && i<=m;++i){ 46 if(!solve(k,i))continue; 47 ++res[i]; 48 for(j=i+mod[k];j<=m;j+=mod[k]){ 49 // if(solve(k,j)) 50 res[j]++; 51 } 52 } 53 for(i=1;i<=m;++i) 54 if(res[i]==7)ans[++act]=i; 55 printf("%d\n",act); 56 for(i=1;i<=act;++i)printf("%d\n",ans[i]); 57 return 0; 58 }
本文为博主原创文章,转载请注明出处。