UOJ20 解方程
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
Description
已知多项式方程:
a0+a1*x+a2*x^2+...+an*x^n=0
求这个方程在[1,m]内的整数解(n和m均为正整数)。
Input
第一行包含2个整数n、m,每两个整数之间用一个空格隔开。
接下来的n+1行每行包含一个整数,依次为a0,a1,a2,...,an。
Output
第一行输出方程在[1,m]内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1,m]内的一个整数解。
Sample Input
2 10
2
-3
1
2
-3
1
Sample Output
2
1
2
1
2
HINT
对于100%的数据,0<n≤100,|ai|≤1010000,an≠0,m≤1000000。
正解:模意义下相等
解题报告:
这道题的画风可以说是NOIP的day2T3中最奇怪的了,算法简单,只是谁想得到联赛T3考这种题目...
首先可以明确,假设本来某个x就成立,那么我把系数和x的次幂都取一个模,这个式子同样成立。所以考虑取几个模数,然后对于式子整体取模,并且检验,如果都等于0我们就可以视为原式相等。
但是这个做法只有70分。考虑如何优化,因为如果x大于模数,那么可以发现x+p再代入原式,得到的答案没有任何区别,所以我们可以把模数取小一点,为了保证正确率,模数取多一点,然后我们只对于每个模数检验0到模数-1,因为大了就没有意义了。这样的做法可以获得100分。但是模数要取得好,我试了很久,发现最少要取3个,少了就肯定会错了...
1 //It is made by ljh2000 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long LL; 15 #define RG register 16 const int MAXN = 50011; 17 int n,m,len,pcnt=2,prime[12]={23333,22877,19997}; 18 int a[12][MAXN],now_ans,xx,ss,ans[12][MAXN],cnt,dui[1000011]; 19 char ch[10011]; 20 bool fu[150]; 21 22 inline int getint() 23 { 24 int w=0,q=0; char c=getchar(); 25 while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 26 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; 27 } 28 29 inline bool check(RG int x){ 30 for(RG int i=0;i<=pcnt;i++) 31 if(ans[i][x%prime[i]]!=0) return false; 32 return true; 33 } 34 35 inline void work(){ 36 n=getint(); m=getint(); 37 for(RG int i=0;i<=n;i++) {//读入第i个系数 38 scanf("%s",ch); len=strlen(ch); if(ch[0]=='-') fu[i]=1; 39 for(RG int o=0;o<=pcnt;o++) {//分别求出对于每个模数意义下的系数的实际值 40 ss=1; 41 for(RG int j=len-1;j>=1;j--) { 42 a[o][i]+=(ch[j]-'0')*ss; a[o][i]%=prime[o]; 43 ss*=10; ss%=prime[o]; 44 } 45 if(fu[i]==0) { a[o][i]+=(ch[0]-'0')*ss; a[o][i]%=prime[o]; ss*=10; ss%=prime[o]; } 46 } 47 } 48 for(RG int i=0;i<=pcnt;i++) { 49 for(RG int x=0;x<prime[i];x++) { 50 xx=1; now_ans=0; 51 for(RG int j=0;j<=n;j++) { 52 if(fu[j]) now_ans-=xx*a[i][j]; else now_ans+=xx*a[i][j]; 53 now_ans%=prime[i]; 54 xx*=x; xx%=prime[i]; 55 } 56 ans[i][x]=now_ans; 57 } 58 } 59 for(RG int i=1;i<=m;i++) if(check(i)) dui[++cnt]=i; 60 printf("%d\n",cnt); 61 for(RG int i=1;i<=cnt;i++) printf("%d\n",dui[i]); 62 } 63 64 int main() 65 { 66 work(); 67 return 0; 68 }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!