题目大意:同解方程 数据范围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]);
}