题目传送门:https://www.luogu.org/problem/show?pid=2312 (习惯性放洛谷的链接)
这一题看起来数据范围巨大无比,需要使用各种玄学方法,看了题解后整个人懵逼了....
对于30%的数据,$0<n≤2$,$|a_{i}|≤100$,$a_{n}!=0$,$m<100$。
该数据范围直接高精度,在$[1,m]$的范围内暴力枚举即可。时间复杂度为$O(n*m*len^{2})$,其中$len$表示高精度计算过程中数字的位数。
对于50%的数据:$0<n<=100$,$|ai|<=10^{100}$,$a_{n} eq 0$,$m<100$。
我们考虑用秦九昭算法对计算进行加速,秦九昭算法思路如图:
该算法目的为在求一元$n$次多项式的值时,将求值需要经过$n^{2}$次乘法和$n$次加法降低至$n$次乘法和$n$次加法。
通过此方法化简,时间复杂度被降低一个$len$。即可拿到50分。
对于100%的数据:$0<n leqslant 100$,$|ai| leqslant 10^{10000}$,$a_{n} eq 0$,$m<1000000$。
我们考虑将高精度的过程去掉。
考虑到同余的某些性质,我们可以对方程的两边对$p$取模($p$为质数),若x满足$(sum _{0}^n a_{i}x^i) =0$,则其必然满足$sum _{0}^n a_{i}x^i$ ≡ 0 (mod p)。
根据同余性质,可将其进一步化简为$sum _{0}^n (a_{i}x^i mod p ) equiv 0 (mod p)$,借助该方法,在枚举x值的过程中便不需要使用高精度计算了。
如果逆着推上面的式子,会发现存在有x,使得$sum _{0}^n (a_{i}x^i mod p ) equiv 0 (mod p)$,但$(sum _{0}^n a_{i}x^i) eq 0$。为了避免推出不可行解,首先$p$尽可能地取大,其次是多选几个$p$分别进行取模,降低通过逆定理求出错误的$x$的概率(我比较懒只对一个大质数取模,结果过掉了)
1 #include<bits/stdc++.h> 2 #define M 2000000 3 #define MOD 100000007 4 #define L long long 5 using namespace std; 6 L rd(){ 7 int zf=1; char c; L k=0; 8 for(c=getchar();!isdigit(c);c=getchar()) if(c=='-') zf=-1; 9 for(;isdigit(c);c=getchar()) k=(k*10+c-'0')%MOD; 10 return k*zf; 11 } 12 L a[M]={0},n,m,p[M]={0},ans=0; 13 bool check(int x){ 14 L sum=0; 15 for(int i=n;i>=0;i--) 16 sum=(a[i]+sum+MOD)*x%MOD; 17 return sum==0; 18 } 19 int main(){ 20 cin>>n>>m; 21 for(int i=0;i<=n;i++) a[i]=rd(); 22 for(int i=1;i<=m;i++) if(check(i)){ 23 ans++; p[i]=1; 24 } 25 printf("%d ",ans); 26 for(int i=1;i<=m;i++) if(p[i]) 27 printf("%d ",i); 28 }