zoukankan      html  css  js  c++  java
  • UVA.12169 Disgruntled Judge ( 拓展欧几里得 )

    UVA.12169 Disgruntled Judge ( 拓展欧几里得 )

    题意分析

    给出T个数字,x1,x3……x2T-1。并且我们知道这x1,x2,x3,x4……x2T之间满足xi = (a * xi-1 + b ) MOD 10001, 求出x2,x4……x2T.

    由于本题中的a和b是未知的,所以需要根据已知条件求出a和b,据说有人暴力枚举a和b然后过了。 所以我来换另一种方法。

    其实我们可以枚举a,并根据x1,x3算出求出可行的b的值。如何做到呢?

    首先我们已经知道
    x2 = (a * x1 + b) MOD 10001
    x3 = (a * x2 + b) MOD 10001
    于是就可以把第一个式子带入到第二个式子中,消去x2,进而得到
    x3 = ( a * (a * x1 + b) + b ) MOD 10001
    而这个式子,可以进一步转化为

    思考一下为什么,等式左边是10001 * k + x3, 对10001 取模后,不就是x3吗? 一开始没有想到,要熟记这个转化!

    对于式子x3 + 10001 * k = ( a * (a * x1 + b) + b ) ,继续稍作化简,可以得到
    (a+1) * b - 10001 * k = x3 - a * a * x1

    而这个式子,就可以用拓展欧几里得算法,求得一组可行解(b,k),我们比较关心的是b的值,在计算完成之后,要记得检验 (x3 - a * a * x1) / gcd( (a+1),10001) 是否为整数,若是的话,就说明这对(a,b) 对于x1,x3是可行的。

    然而题目还给出了x5……等等的奇数序列,我们在依次递推的时候,若发现求出的x5,x7……与原数列不相等,那么说明求出的(a,b)并不work,还要重新求解,题目保证一定有解。

    代码总览

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #define ll long long
    #define nmax 220
    #define MOD 10001
    using namespace std;
    ll a,b,k,c,d;
    int n;
    ll x[nmax];
    void exgcd(ll a, ll b, ll& d, ll& x, ll &y){
        if(!b){
            d = a,x = 1,y = 0;
        }else{
            exgcd(b, a % b, d, y, x);
            y -= x * (a / b);
        }
    }
    bool solve(){
        c = x[3] - a*a*x[1];
        exgcd(a+1,MOD,d,b,k);
        if(c % d == 0){
            b = c / d * b;
            return true;
        }
        else return false;
    
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(scanf("%d",&n) != EOF){
            for(int i =1;i<=2*n;i+=2) scanf("%lld",&x[i]);
            bool isfindall = false;
            for( a = 0;a < MOD;++a){
                if(solve()){
                    for(int j = 2;j<=2*n;++j){
                        isfindall = false;
                        ll tmp = ( (a * x[j-1]) + b)%MOD;
                        if( (j%2!=0) && tmp != x[j]) break;
                        else x[j] = tmp;
                        if(j == 2*n) isfindall = true;
                    }
                    if(isfindall) break;
                }
            }
            for(int i = 2;i<=2*n;i+=2){
                printf("%lld
    ",x[i]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    (转) dedecms中自定义数据模型
    (转)dedecms网页模板编写
    (转)dedecms入门
    (转)浅谈dedecms模板引擎工作原理及自定义标签
    (转)PHP数组的总结(很全面啊)
    (转)echo和print的区别
    (转)dedecms代码详解 很全面
    (转)php 函数名称前的@有什么作用
    (转)PHP正则表达式的快速学习方法
    GIS中mybatis_CMEU的配置方法
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367026.html
Copyright © 2011-2022 走看看