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 }