hdu2769:枚举+同余方程

 题意:有一个随机数生成器  x[i+1]=(a*x[i]+b)%10001

已知  x1,x3,x5...求 x2,x4,x6......

x的个数为 2n (n<=10000) a,b也在 0到10000之间

分析,有 a,b两个未知数,不好解方程,只能通过枚举

比赛的时候想了一下枚举a,b感觉复杂度略大 没敢写(后来据说姿势优美的暴力也能过)

正解是枚举 a,求b

带入x1,x3即可得到一个很简单的exgcd同余方程,对0,10000的每一个a,解出一个b进行验证即可

代码:

#include <iostream>
#include <stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<ctype.h>
using namespace std;
#define mod 10001
long long in[10010];
long long out[10010];
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    long long tt=exgcd(b,a%b,x,y);
    long long t;
    t=x;
    x=y;
    y=(t-a/b*y);
    return tt;

}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%I64d",in+i);
    int ok=0;
    for(long long i=0;i<=10000;i++)
    {
        long long c=((in[1]-i*i*in[0]%10001)%10001+10001)%10001;
        long long a=i+1;
        long long b=-10001;
        long long x,y;
        long long d=exgcd(a,b,x,y);
        if(c%d)
            continue;
        long long t=abs(b/d);
        x*=c/d;
        x=(x%t+t)%t;
        for(int j=0;j<n;j++)
        {
            out[j]=(i*in[j]+x)%10001;
            if(j==n-1)
            {
                ok=1;
                break;
            }
            if(((i*out[j]+x)%10001)!=in[j+1])
                break;
        }
        if(ok)
            break;
    }
    if(!ok)
    {
        puts("bug");
    }
    for(int i=0;i<n;i++)
    {
        printf("%I64d\n",out[i]);
    }
    return 0;
}

 

posted @ 2014-10-09 13:31  PlasticSpirit  阅读(220)  评论(0编辑  收藏  举报