题意:
看白书
要点:
再一个办法就是枚举a,利用x1,x3求出b,判断所有x的关系能不能满足a,b。
如何通过a,x1,x3求出b呢。
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);
这样就成了求 b 和 -k,满足这个式子,就是扩展欧几里得的一般用法
这是理论分析,然后实际做题中我WA了一次,TLE了一次,WA的原因是a我看错题了,题目中没有给定a的范围,我以为也是0~10000。TLE的原因是我一开始想直接用x[i]和x[I-2]判断b是否成立,感觉也没慢到那去,但就是TLE了,没办法只能按别人的来。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ll long long
int x[500];
ll gcd(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = 1; y = 0;
return a;
}
ll ans=gcd(b, a%b, x, y);
ll temp = x;
x = y;
y = temp - a / b*y;
return ans;
}
int main()
{
int n,i;
ll a, t;
scanf("%d", &n);
for (i = 1; i <=2*n; i+=2)
scanf("%d", &x[i]);
ll xx, yy;
for (a = 0;; a++)
{
ll d = gcd(10001, -(a + 1), xx, yy);
ll t = a*a*x[1] - x[3];
if (t%d != 0)
continue; //不能整除直接无解
yy *= t/d;
bool flag = true;
for (i = 2; i <= 2 * n; i++)
{
if (i & 1) //同位与,相当与取奇数
{
if (x[i] != (a*x[i - 1] + yy) % 10001)
{
flag = false;
break;
}
}
else
x[i] = (a*x[i - 1] + yy) % 10001;
}
if (flag)
break;
}
for (i = 2; i <= 2*n; i+=2)
printf("%lld\n",x[i]);
return 0;
}