题目大意:同解方程 数据范围m<=10^8
O(m)做法见 http://blog.csdn.net/popoqqq/article/details/40984859
O(m)跪了你就当我没辙么?
首先找到一个比较靠谱的第一个质数 将对第一个质数取模为0的值全都存在一个数组里
由于这个是有循环节的 所以我们只需要处理出[0,p-1]中对第一个质数取模为0的数就可以搞出所有了
然后对于这个数组里的所有数用剩余的质数验证一遍就行了
时间复杂度未知 但是第一个质数必须靠谱 如果第一个质数被卡掉那就退化成O(m)了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 110 using namespace std; typedef long long ll; const int prime[]={30011,11261,14843,19997,10007,21893}; int n,m,stack[1001001],top; int ans[110],tot; ll a[M][6],f[30011][6]; inline ll F(int x,int j) { int i; ll re=0; for(i=n;~i;i--) re=(re*x+a[i][j])%prime[j]; return re; } inline void Input(int x) { static char s[10100]; int i,j; bool flag=false; scanf("%s",s+1); for(i=1;s[i];i++) { if(s[i]=='-') flag=true; else for(j=0;j<6;j++) a[x][j]=( (a[x][j]<<1) + (a[x][j]<<3) + s[i]-'0' )%prime[j]; } if(flag) for(j=0;j<6;j++) a[x][j]=prime[j]-a[x][j]; } int main() { //freopen("equation.in","r",stdin); int i,j; cin>>n>>m; for(i=0;i<=n;i++) Input(i); for(j=0;j<6;j++) for(i=0;i<prime[j];i++) f[i][j]=F(i,j); for(i=0;i<prime[0];i++) { if(f[i%prime[0]][0]==0) stack[++top]=i; } for(i=1;i<=top;i++) { if(stack[i]+prime[0]>m) break; stack[++top]=stack[i]+prime[0]; } for(i=1;i<=top;i++) { if(stack[i]>m) break; for(j=1;j<6;j++) if(f[stack[i]%prime[j]][j]) break; if(j==6) ans[++tot]=stack[i]; } cout<<tot<<endl; for(i=1;i<=tot;i++) printf("%d\n",ans[i]); }
Vijos P1915 解方程 加强版 还是Hash大法好!
原文:http://blog.csdn.net/popoqqq/article/details/41077435