• UVA 12169 Disgruntled Judge【扩展欧几里德】


    题意:随机选取x1,a,b,根据公式xi=(a*xi-1+b)%10001得到一个长度为2*n的序列,奇数项作为输入,求偶数项,若有多种,随机输出一组答案。

    思路:a和b均未知,可以考虑枚举a和b,时间复杂度为10000*10000*100,但是题目数据比较水,这样枚举也是能过的。高效的做法是:枚举a,根据以下公式求出b。

    a*x1+b - MOD*y1 = x2;

    a*x2+b - MOD*y2 = x3;

    解得:

    x3 - a*a*x1=(a+1)*b + MOD * y;

    该方程为关于变量b的模线性方程 ,用扩展欧几里得算法解出一个解b0,(当gcd(a+1,MOD)==1) 则解出的为一个同余系;

    b = b0 + MOD*k (k为任意整数);(该方程对应了 b = b0 + MOD' * k ,其中MOD' 为MOD/ gcd(a+1,MOD) ); 只需要检验一个b即可

    但是当gcd(a+1,MOD)不等1时,直接用b0求解是有问题的因为解不在是MOD的同余系而是MOD‘的同余系;

    所以正解应该是算出b0然后解出0 - 10000范围内的 可行b 然后检验; 算法复杂度为 O(nlogn*100);

    #include<stdio.h>
    #include<string.h>
    const int mod=10001;
    typedef long long ll;
    ll x[222];
    ll ex_gcd(ll a,ll b,ll &x,ll &y){
        if(!b){
            x=1,y=0;
            return a;
        }
        int ans=ex_gcd(b,a%b,y,x);
        y-=a/b*x;
        return ans;
    }
    int main(){
        int n,i;
        while(~scanf("%d",&n)){
            n*=2;
            for(i=1;i<n;i+=2){
                scanf("%lld",&x[i]);
            }
            long long a,b,c,d,y;
            for(a=0;;a++){
                c=x[3]-a*a*x[1];
                d=ex_gcd(a+1,mod,b,y);
                if(c%d)    continue;
                b=b*c/d;
                for(i=2;i<=n;i++){
                    if(i&1){
                        if(x[i]!=(a*x[i-1]+b)%mod)
                            break;
                    }else
                        x[i]=(a*x[i-1]+b)%mod;
                }
                if(i>n)    break;
            }
            for(i=2;i<=n;i+=2)
                printf("%lld
    ",x[i]);
        }
        return 0;
    }

     http://www.ithao123.cn/content-4532209.html

  • 相关阅读:
    软件測试培训笔记
    spring test---測试SpringMvc初识
    第1章第3节 线性表的比較
    Remove Duplicates from Sorted List leetcode
    泛型
    我的改进版2048(1)
    docker镜像和加速
    在 Azure Web 应用中创建 PHP 应用程序
    使用 Azure 门户创建 Windows 虚拟机
    使用 Azure 门户创建 Linux 虚拟机
  • 原文地址:https://www.cnblogs.com/L-King/p/5757643.html
Copyright © 2020-2023  润新知