例10-2 uva12169(扩展欧几里得)
题意:已知xi=(a*xi-1+b) mod 10001,且告诉你x1,x3.........x2*t-1,让你求出其偶数列
思路:
枚举a,然后通过x1,x3求出b,再验证是否合适
1.设a, b, c为任意整数。若方程ax+by=c的一组整数解为(x0,y0),则它的任
意整数解都可以写成(x0+kb', y0-ka'),其中a'=a/gcd(a,b),b'=b/gcd(a,b),k取任意整数。
2.设a, b, c为任意整数,g=gcd(a,b),方程ax+by=g的一组解是(x0,y0),则
当c是g的倍数时ax+by=c的一组解是(x0c/g, y0c/g);当c不是g的倍数时无整数解。
x2 = (a * x1 + b) % 10001;
x3 = (a * x2 + b) % 10001;
联立2个式子
x3 = (a * (a * x1 + b) % 10001 + b ) % 10001;
x3 = (a * (a * x1 + b) + b) % 10001;
所以 x3 + 10001 * k = a * a * x1 + (a + 1) * b;
x3 - a * a * x1 = (a + 1) * b + 10001 * (-k);
x3 - a*a*x1已知,就转化成ax+by = c /*扩展欧几里得,在中途再用②判定是否是整数解即可
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <map> #include <vector> using namespace std; typedef long long ll; typedef unsigned long long ull; const int mod =10001; ll f[mod]; void gcd(ll a , ll b ,ll &d, ll &x,ll &y) { if(!b) { d = a ; x = 1; y = 0; return ; } else { gcd(b , a % b ,d , y , x); y -= x * (a / b); return ; } } int main() { int n; int t; scanf("%d",&t); memset(f,0,sizeof(f)); for(int i = 1; i <= 2*t; i+=2) scanf("%I64d",&f[i]); for(int a = 0; a < 10001; a++) { ll k , b , d; ll c = (f[3] - a * a * f[1]); gcd(mod, a + 1, d , k, b); if(c % d) //当ax+by = c时,g=gcd(a,b),当c是g倍数时一组解(x*c/g,y*c/g),否则无整数解 continue; b = b*c/d; int flag; for(int i = 2; i <= 2*t; i++) { flag = 1; int tmp = (a*f[i-1]+b)%mod; if(i%2) { if(tmp != f[i]) { flag = 0; break; } } else f[i] = tmp; } if(flag) break; } for(int i = 2; i <= 2*t; i+=2) { printf("%d\n",f[i]); } return 0; }