3.解方程
(equation.cpp/c/pas)
【问题描述】
已知多项式方程:
求这个方程在[1, m]内的整数解(n和m均为正整数)。
【输入】
输入文件名为equation.in。
输入共n+2行。
第一行包含2个整数n、m,每两个整数之间用一个空格隔开。
接下来的n+1行每行包含一个整数,依次为a0,a1,a2,……,an。
【输出】
输出文件名为equation.out。
第一行输出方程在[1, m]内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。
【输入输出样例1】
equation.in |
equation.out |
2 10 1 -2 1 |
1 1 |
【输入输出样例2】
equation.in |
equation.out |
2 10 2 -3 1 |
2 1 2 |
【输入输出样例3】
equation.in |
equation.out |
2 10 1 3 2 |
0 |
【数据说明】
对于30%的数据,0<n≤2,|ai|≤100,an≠0,m≤100;
对于50%的数据,0<n≤100,|ai|≤10100,an≠0,m≤100;
对于70%的数据,0<n≤100,|ai|≤1010000,an≠0,m≤10000;
对于100%的数据,0<n≤100,|ai|≤1010000,an≠0,m≤1000000。
【思路】
取自他人。
由a的大小可以看出题目应该要MOD一个prime。
只需要依次判断1..prime中的v是否可以通过模prime使方程式为0,注意for反向枚举才是明智之举。对于m内prime外的其他数可以通过模prime映射到prime之内判断。
多试几个prime基本可以确定答案。
教训:有时候数据的范围可以在一定程度上反应出题目的思路。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int maxn = 100+5; 5 const int primes[]={10007,10917,30071}; 6 7 long long a[maxn][3]; 8 bool f[100000][3]; 9 int cnt[1000010]; 10 char s[10010]; 11 int n,m; 12 int calc(int v,int j) { //计算v是否不可以通过模j而为0 13 long long tmp=0; 14 for(int i=n; i>=0;i--) //逆序枚举 15 tmp=(tmp*v+a[i][j]) % primes[j]; 16 17 return tmp!=0; 18 } 19 int main() { 20 scanf("%d%d",&n,&m); 21 for(int i=0;i<=n;i++) { 22 scanf("%s",s); 23 int len=strlen(s); 24 int sign=1; 25 for(int l=0;l<len;l++) 26 if(s[l]=='-') sign=-1; 27 else 28 for(int j=0;j<3;j++) 29 a[i][j]=(a[i][j]*10+s[l]-'0')%primes[j]; 30 if(sign==-1) //转换符号 31 for(int j=0;j<3;j++) 32 a[i][j]=primes[j]-a[i][j]; 33 } 34 35 for(int j=0;j<3;j++) 36 for(int i=0;i<primes[j];i++) //i from [0..primes[j]] 37 f[i][j]=calc(i,j); 38 39 for(int i=1;i<=m;i++) { 40 int flag=true; 41 for(int j=0;j<3;j++) if(f[i%primes[j]][j]){ //i%primes[j]转化 42 flag=false; break; 43 } 44 if(flag) cnt[++cnt[0]]=i; 45 } 46 printf("%d ",cnt[0]); 47 if(cnt[0]) for(int i=1;i<=cnt[0];i++) printf("%d ",cnt[i]); 48 return 0; 49 }