题目链接
题意
现在有一个长度为2n的序列B,序列满足 B i = ( a ∗ B i − 1 + b ) m o d 10001 B_i=(a*B_{i-1}+b)\ mod\ 10001 Bi=(a∗Bi−1+b) mod 10001,其中a和b两个参数未知。现在给定下标为奇数的序列B,求下标为偶数的序列B。求出任意一个即可.
思路
我们先写一下式子
B
3
=
(
a
B
2
+
b
)
%
m
o
d
=
k
1
m
o
d
+
a
B
2
+
b
B_3=(aB_2+b)\%mod=k_1mod+aB_2+b
B3=(aB2+b)%mod=k1mod+aB2+b
B
2
=
(
a
B
1
+
b
)
%
m
o
d
=
k
2
m
o
d
+
a
B
1
+
b
B_2=(aB_1+b)\%mod=k2mod+aB_1+b
B2=(aB1+b)%mod=k2mod+aB1+b
把第二个式子带到第一个式子可以的到
B
3
=
(
k
1
+
a
k
2
)
m
o
d
+
a
2
B
1
+
(
a
+
1
)
b
B_3=(k_1+ak_2)mod+a^2B_1+(a+1)b
B3=(k1+ak2)mod+a2B1+(a+1)b
如果把mod的系数看成一个整体,那么这个式子可以化简为
K
m
o
d
+
(
a
+
1
)
b
=
B
3
−
a
2
B
1
Kmod+(a+1)b=B_3-a^2B_1
Kmod+(a+1)b=B3−a2B1
由于a和b的范围都不超过10000,那么我们枚举一下a,就得到一个关于K和b的二元不定方程,利用扩欧求得b后带回原序列进行验证,如果符合公式那么我们就找到了一组合法的a和b,就可以求出偶数序列了。
代码
#include <algorithm>
#include <cstdio>
#include <cstring>
#define inf 1ll << 62
#define cases(yjq) for (int cas = 1; cas <= (int)yjq; ++cas)
using namespace std;
const int mod = 10001;
int n;
long long A[10005], B[10005];
int cnt;
inline long long Abs(long long x) { return x < 0 ? -x : x; }
long long exgcd(long long a, long long b, long long& x, long long& y) {
if (!b) {
x = 1;
y = 0;
return a;
}
int t = exgcd(b, a % b, y, x);
y -= a / b * x;
return t;
}
bool solve(long long a, long long b, long long c, long long& x, long long& y) {
long long g = exgcd(a, b, x, y);
if (c % g) return false;
x *= c / g;
y *= c / g;
long long tmp = Abs(b / g);
x = (x % tmp + tmp) % tmp;
cnt = 0;
for (int i = 0; x + i * tmp <= 10000; ++i) B[cnt++] = x + i * tmp;
y = (c - a * x) / b;
return true;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", A + i);
long long x, y;
int a;
for (a = 0; a <= 10000; ++a) {
if (!solve(a + 1, mod, A[2] - 1ll * a * a * A[1], x, y)) continue;
bool ok = false;
for (int i = 0; i < cnt; ++i) {
bool gg = false;
for (int j = 2; j <= n; ++j) {
if ((A[j] - a * a * A[j - 1] - a * B[i] - B[i]) % mod != 0) {
gg = true;
break;
}
}
if (!gg) {
for (int j = 1; j <= n; ++j) printf("%d\n", (a * A[j] + B[i]) % mod);
ok = true;
break;
}
}
if (ok) break;
}
return 0;
}