题解:P2312 [NOIP2014 提高组] 解方程
题目大意
在 看起来很吓人的方程。
分析
对于
100\% 的数据:0<n\le 100,|a_i|\le 10^{10000},a_n≠0,m<10^6 。
相信你一眼就看到了 自然而然的想到枚举
问题来了,怎么逗?
首先,我问先来表示出题干所给的函数值:
显然,若
我们来简化一下
- 若
f(x)\%mod=0 ,那f(x) 就有可能为0 。 - 若
f(x)\%mod=0 ,f(x)\%Mod=0 ,且mod\ne Mod ,那f(x) 就很有可能为0 。
我们就可以用
bool f(int x0,int M,long long *t){//m是模数,t是对应的a数组
long long res=t[n];
for(int i=n-1;i>=0;i--) res=(res*x0+t[i])%M;
return res==0;
}
推到这里,我们就不得不面对
数值这么大,自然不能用直接读入。我们可以对其进行哈希,利用快读的思想,就能对其进行取模:
for(int i=0;i<=n;i++){//快读应该都会吧?
long long x=0,X=0; bool F=false; char c=getchar();
while(c<'0'||'9'<c){if(c=='-') F=true;c=getchar();}
while('0'<=c&&c<='9'){
x=(x<<3)+(x<<1)+c-'0',X=(X<<3)+(X<<1)+c-'0';
x%=mod,X%=Mod;//边乘边取模
c=getchar();
}
a[i]=F?mod-x:x,A[i]=F?Mod-X:X;//这里一定要小心,不要直接拿负数取模!
}
code
#include<bits/stdc++.h>
using namespace std;
const int mod=10007,Mod=1e9+7;
int n,m,cnt,ans[100001];
long long a[102],A[102];
bool vis[mod];
bool f(int x0,int M,long long *t){
long long res=t[n];
for(int i=n-1;i>=0;i--) res=(res*x0+t[i])%M;
return res==0;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++){
long long x=0,X=0; bool F=false; char c=getchar();
while(c<'0'||'9'<c){if(c=='-') F=true;c=getchar();}
while('0'<=c&&c<='9'){
x=(x<<3)+(x<<1)+c-'0',X=(X<<3)+(X<<1)+c-'0';
x%=mod,X%=Mod;
c=getchar();
}
a[i]=F?mod-x:x,A[i]=F?Mod-X:X;
}
for(int i=0;i<mod;i++) if(f(i,mod,a)) vis[i]=true;
for(int i=1;i<=m;i++) if(vis[i%mod]&&f(i,Mod,A)) ans[++cnt]=i;
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++) printf("%d\n",ans[i]);
return 0;
}