[数学杂题 随机]【NOIP2014】解方程

这是一道不是很远古的 noip 题。
由于很久之前看过,就只能写一写可能不太有理有据的思考过程了:
这样一个问题,数据范围较大,系数都是高精的,一般的方法不太可做。应该需要从一些玄学的方向考虑。
首先肯定排除记下高精数进行操作。那么可能就能想到模一个数了。
f(x)=0 则显然一定有 f(x)%P=0 。但反过来推不一定。所以就多找几个模数试一试,若某个 x 在这些模数下都成立 ,则基本就是答案了。
想一想复杂度。
已知 x f(x)%P 可以用秦九韶,避免幂的操作,做到 O(n)
而且对与每个模数 P f(x)f(x+P)(modP),所以只需算 x=1 P 的值即可。
P 不要取太大,多取几个就能过了。

#include<cstdio>
#include<algorithm>
using namespace std;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
const int lstp[5]={23333,10007,2137,9817};
const int maxn=105,maxm=1000005;
int n,m,a[10][maxn],cnt[maxm],ans[maxm];
int F(int k,int x){
    int res=a[k][n];
    for(int i=n-1;i>=0;i--) res=(res*x+a[k][i])%lstp[k];
    return res;
}
void Solve(int k){
    for(int i=1;i<=lstp[k]&&i<=m;i++) if(F(k,i)==0){
        for(int j=i;j<=m;j+=lstp[k]) cnt[j]++;
    }
}
int main(){
    freopen("uoj20.in","r",stdin);
    freopen("uoj20.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++){
        char ch=gc(); int ff=1;
        while(!('0'<=ch&&ch<='9')) ch=='-'?ff=-1:0, ch=gc();
        while('0'<=ch&&ch<='9'){
            for(int j=0;j<=3;j++) a[j][i]=((a[j][i]<<3)+(a[j][i]<<1)+ch-'0')%lstp[j];
            ch=gc();        
        }
        if(ff==-1) for(int j=0;j<=3;j++) a[j][i]=-a[j][i];
    }
    for(int j=0;j<=3;j++) Solve(j);
    for(int i=1;i<=m;i++) if(cnt[i]==4) ans[++ans[0]]=i;
    printf("%d\n",ans[0]);
    for(int i=1;i<=ans[0];i++) printf("%d\n",ans[i]);
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值