专栏文章
题解:P2312 [NOIP2014 提高组] 解方程
P2312题解参与者 10已保存评论 17
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 17 条
- 当前快照
- 1 份
- 快照标识符
- @miqgekmw
- 此快照首次捕获于
- 2025/12/04 04:22 3 个月前
- 此快照最后确认于
- 2025/12/04 04:22 3 个月前
题目大意
在 到 的范围内解一个看起来很吓人的方程。
分析
对于 的数据: 。
相信你一眼就看到了 的离谱范围,但 的范围却相对较小。这是,就会自然而然的想到枚举 ,来逗答案(四川方言,意为挨个试出答案)。
问题来了,怎么逗?
首先,我问先来表示出题干所给的函数值:
显然,若 ,则 为正确答案。
我们来简化一下 :
- 若 ,那 就有可能为 。
- 若 ,,且 ,那 就很有可能为 。
我们就可以用 分别对两个数(绝对不能有倍数关系,最好都是质数)取模,看是否为 。于是,我们就能通过下面的代码来检验 是否为正确答案:
CPPbool 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;
}
推到这里,我们就不得不面对 的离谱数据。
数值这么大,自然不能用直接读入。我们可以对其进行哈希,利用快读的思想,就能对其进行取模:
CPPfor(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
CPP#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;
}
相关推荐
评论
共 17 条评论,欢迎与作者交流。
正在加载评论...