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\n",x[i]);
    }
    return 0;
}

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

时间: 2024-10-07 01:26:29

UVA 12169 Disgruntled Judge【扩展欧几里德】的相关文章

hdu 2769 uva 12169 Disgruntled Judge 拓展欧几里德

//数据是有多水 连 10^10的枚举都能过 关于拓展欧几里德:大概就是x1=y2,y1=x2-[a/b]y2,按这个规律递归到gcd(a,0)的形式,此时公因数为a,方程也变为a*x+0*y=gcd(a,0)的形式,显然解为x=1,y=0,然后再递归回去就能得到解(a*x+b*y=gcd(a,b)的解) 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm&g

uva 12169 Disgruntled Judge

法一直接暴力枚举a和b的值,法二扩展欧几里德算法. #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <

UVA 12169 Disgruntled Judge 枚举+扩展欧几里得

题目大意:有3个整数 x[1], a, b 满足递推式x[i]=(a*x[i-1]+b)mod 10001.由这个递推式计算出了长度为2T的数列,现在要求输入x[1],x[3],......x[2T-1], 输出x[2],x[4]......x[2T]. T<=100,0<=x<=10000. 如果有多种可能的输出,任意输出一个结果即可. 由于a和b都小于等于10000,直接枚举a和b暴力可以过.但是有没有更快的方法呢? 首先令递推式的i=2,那么x[2]=(a*x[1]+b)mod 1

HDOJ 2769 Disgruntled Judge 扩展GCD

扩展GCD: 枚举a,扩展GCD求b,再暴力检查 Disgruntled Judge Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 329    Accepted Submission(s): 142 Problem Description Once upon a time, there was an nwerc judge with

12169 - Disgruntled Judge

枚举a和b...耗时0.126        显然这不是最好的方法,最好的方法是至需枚举a,利用扩展欧几里德算法求出线性模方程.求的b:其实我也还没有理解,等学会了再来更新.. #include<bits/stdc++.h> using namespace std; int T,a[109],b[109]; void solve() { for(int i=10000;i>=0;--i) for(int j=10000;j>=0;--j){ int kase=0; bool ok=

【UVA】12169-Disgruntled Judge(暴力or欧几里得)

可能由于后台数据的原因,这道题直接暴力枚举a,b进行判断也能过,不过跑的时间长,效率太差了. 14021006 12169 Disgruntled Judge Accepted C++ 0.876 2014-08-11 08:46:28 不说了,比较无脑. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #incl

hud2769 Disgruntled Judge(扩展欧几里德算法)

题目链接:点击打开链接 题目描述: 给出三个数x1,a,b,然后根据递推公式xi=(axi-1+b)mod10001,计算出了一个长度为2T的数列.然后把T和x1,x3,x5··· x2T-1写到输入文件,x2,x4,x4,···x2T作为输出文件 输入保证T<=100,如果有多种可能,任意输出一种即可 解题思路:如果知道a,我们就可以通过x1,x3,计算出b.有了x1,a,b我们就可以在O(T)的时间内求的整个序列.如果在计算中发现和输入矛盾,则这个a是非法的.由于mod10001,所以a是0

uva 10104 Euclid Problem (数论-扩展欧几里德)

 Euclid Problem  The Problem From Euclid it is known that for any positive integers A and B there exist such integers X and Y that AX+BY=D, where D is the greatest common divisor of A and B. The problem is to find for given A and B corresponding X, Y

扩展欧几里德算法

文章来源:http://blog.csdn.net/zhjchengfeng5/article/details/7786595 谁是欧几里德?自己百度去 先介绍什么叫做欧几里德算法 有两个数 a b,现在,我们要求 a b 的最大公约数,怎么求?枚举他们的因子?不现实,当 a b 很大的时候,枚举显得那么的na?ve ,那怎么做? 欧几里德有个十分又用的定理: gcd(a, b) = gcd(b , a%b) ,这样,我们就可以在几乎是 log 的时间复杂度里求解出来 a 和 b 的最大公约数了