[NOIP2014]解方程 (暑假ACM1 H)
题意
求方程a0+a1x+a2x2+⋯anxn=0在[1,m]内的解。
对于100% 的数据:0<n<=100,|ai|<=1010000,an≠0,m<1060
题解
当时是sxk大佬给我说的他的思路,因为题目有暗示 Hint:如果那是个模方程,求 (mod 10007)时 x%10007的各种解,那么我就会做了。
所以他就说先对系数取模,然后求出[0,10006]的解,然后如果一个解是x0,那么(x0+10007)也是一个解,因为在将各种次方展开时,有10007系数的都模掉了,就变成了原方程。
所以我看了看数据,ai怎么模?高精度???我问出了这个愚蠢的问题,可以利用快读边读入边取模,而且这个问题原来遇到过,我都忘了[菜鸡]
不过我从一开始就产生了一种顾虑,就是就算是模方程,那左边计算不取模就可能爆掉,取模万一是10007的倍数最后得到0,不过这并不是一个正确解。
还好这个是正确的,不然又打脸。
后来又想到了取多个模数,并且想到了要用秦九韶算法,可是却跑偏了,因为要枚举[1,m]的数,就因为过不去,最后没敲。
现在想想,其实挺简单的。
#include<bits/stdc++.h> using namespace std; #define ll long long const int mod1=10007; const int mod2=1000000007; const int maxm=1000005; int n,m; ll a[105],b[105]; int ans[maxm]; bool cx[10010]; inline void read(int i){ ll x=0,y=0;int f=0;char ch=getchar(); while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();} while(isdigit(ch)){x=x*10%mod1+ch-'0';y=y*10%mod2+ch-'0';ch=getchar();} if(f) x=-x,y=-y; a[i]=x;b[i]=y; } bool nice(ll x){ ll ret=0; for(int i=n;~i;i--) ret=(ret*x+a[i])%mod1; return !ret; } bool sto324(ll x){ ll ret=0; for(int i=n;~i;i--) ret=(ret*x+b[i])%mod2; return !ret; } int main(){ scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) read(i); //for(int i=0;i<=n;i++) printf("%d %d\n",a[i],b[i]); for(int i=0;i<mod1;i++) if(nice(i)) cx[i]=true; for(int i=1;i<=m;i++) if(cx[i%mod1]&&sto324(i)) ans[++ans[0]]=i; for(int i=0;i<=ans[0];i++) printf("%d\n",ans[i]); }