洛谷 2312 / bzoj 3751 解方程——取模
题目:https://www.luogu.org/problemnew/show/P2312
https://www.lydsy.com/JudgeOnline/problem.php?id=3751
惭愧……先听了同学讲它,又看了题解,才A。
取一些模数就能限制时间复杂度并有一些概率正确。取模后常数也能取模,就不用高精度了!而且m以内的数只用算 0~模数-1 的值,表示取模后是该值的数在模该值意义下答案是否为0。
bzoj上的数据需要精心选取模数。据说2e4左右的效果最好?试了几次终于A了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=105,M=1e4+5,A=1e6+5,K=15,C=7,D=4e4+5; int n,m,a[N][M],nm[N],c[N],ans[A],cnt; bool fx[N],flag; int zs[K]={15671,29501,18919,16843,23767,30271,24443}; bool vis[K][D]; void solve(int p) { for(int i=0;i<=n;i++) { c[i]=0; for(int j=1;j<=nm[i];j++) c[i]=(c[i]*10+a[i][j])%p; if(fx[i]) c[i]=(-c[i]+p)%p; } } void calc(int bh,int x,int p) { int cr=0; for(int i=n;i>=0;i--) cr=(cr*x%p+c[i])%p; vis[bh][x]=(!cr); } int main() { scanf("%d%d",&n,&m); char ch=getchar(); for(int i=0;i<=n;i++) { while(ch>'9'||ch<'0'){ if(ch=='-') fx[i]=1; ch=getchar();} while(ch>='0'&&ch<='9') a[i][++nm[i]]=ch-'0',ch=getchar(); } for(int i=0;i<C;i++) { solve(zs[i]); for(int j=0;j<zs[i]&&j<=m;j++) calc(i,j,zs[i]); } for(int i=1;i<=m;i++) { flag=0; for(int j=0;j<C;j++) if(!vis[j][i%zs[j]]) {flag=1;break;} if(!flag) ans[++cnt]=i; } printf("%d\n",cnt); for(int i=1;i<=cnt;i++) printf("%d\n",ans[i]); return 0; }