UVA 12169 - Disgruntled Judge(拓展欧几里得)
题目链接 https://cn.vjudge.net/problem/UVA-12169
【题意】
有一个长度为T的整数序列x,已知x[i]=(a*x[i]-1+b) mod 10001,且告诉你x[1],x[3]………x[2*T-1],让你求出其偶数项分别是多少,输出任意解即可
【思路】
因为取模的范围不大,所以可以枚举a(0~10000),然后根据x[1],x[3]计算出b,然后再去验证(a,b)对整个序列是否成立
x[2] = (a*x[1]+b)% 10001
x[3] = (a*x[2]+b)% 10001
联立上面两式,可得
x[3]=(a* (a*x[1]+b)%10001 +b) % 10001
即 x[3]=(a* (a*x[1]+b)+b) % 10001
即 x[3]=(a*a*x[1]+(a+1)*b) % 10001
也就是说(a+1)*b-10001k=x[3]-a*a*x1(k为整数)
只有b,k为未知量,这样就转换成了求解ax+by=c的整数解问题了,用扩展欧几里得计算
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=220;
void gcd(ll a,ll b,ll& d,ll& x,ll& y){
if(0==b){d=a;x=1;y=0;}
else {gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
int n;
ll f[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=2*n;i+=2) scanf("%lld",&f[i]);
for(ll a=0;a<10001;++a){
ll d,b,k,c=f[3]-a*a*f[1];
gcd(a+1,-10001,d,b,k);
if(c%d) continue;
b*=c/d;
bool ok=true;
for(int i=2;i<=2*n;++i){
ll tmp=(a*f[i-1]+b)%10001;
if((i&1) && tmp!=f[i]){ok=false;break;}
f[i]=tmp;
}
if(ok){
for(int i=2;i<=2*n;i+=2){
printf("%lld\n",f[i]);
}
break;
}
}
return 0;
}