Uva12169 扩展欧几里得模板

Uva12169(扩展欧几里得)

题意:

已知 $x_i=(a*x_{i-1}+b) mod 10001$,且告诉你 $x_1,x_3.........x_{2t-1}$, 让你求出其偶数列

解法:

令$ x_2=(ax_1+b)mod 10001$,$x_3= (ax_2+b)mod 10001$

解得:$x_3+10001k=a^{2}x_1+( a + 1) b$

移像得:$x_3 - a^{2}x_1=( a + 1) b - 10001k$

把 $b$ 和$(-k)$看成是未知数,这就是求解一个 $ax+by=c$ 的方程,扩展欧几里得可解

见代码

 1 /*
 2   由于a的范围只有1e5,所以我们可以直接枚举a的所有值,
 3   然后根据公式求出b的值,之后根据a和b的值递推所有的原数列的值
 4   期间会用到扩展欧几里得解线性方程组
 5   如果有不一样的,说明就不存在,重来
 6 */
 7 #include<cstdio>
 8 using namespace std;
 9 typedef long long ll;
10 const int mod = 10001;
11 ll f[2*10000], n;
12 
13 //扩展欧几里得解线性方程组
14 ll exgcd(ll a, ll b, ll &x, ll &y){
15     if (b == 0){
16         x = 1, y = 0;
17         return a;
18     }
19     ll r = exgcd(b, a%b, x, y);
20     ll t = x;
21     x = y;
22     y = t - a / b*y;
23     return r;
24 }
25 
26 inline bool linear_equation(ll a, ll b, ll c, ll &x, ll &y){
27     ll d = exgcd(a, b, x, y);
28     if (c%d) return false;
29     ll k = c / d;
30     x *= k; y *= k;    //求得的只是其中一组解
31     return true;
32 }
33 
34 bool check(ll a,ll b) {
35     for (int i = 2; i <= n * 2; i++) {
36         ll now = (a*f[i - 1] + b) % mod;
37         if (i & 1) {
38             if (now == f[i]) continue;
39             else return false;
40         }
41         else f[i] = now;
42     }
43     return true;
44 }
45 
46 int main() {
47     scanf("%d", &n);
48     for (int i = 1; i <= n * 2; i += 2) scanf("%lld", &f[i]);
49     for (ll a = 0; a <= 10001; a++) {
50         ll b, k;
51         if (!linear_equation(a + 1, mod, f[3] - a*a*f[1], b, k))continue;
52         if (check(a, b)) break;
53     }
54     for (int i = 2; i <= 2 * n; i+=2) {
55         printf("%lld
", f[i]);
56     }
57     return 0;
58 }
原文地址:https://www.cnblogs.com/romaLzhih/p/9491202.html