题意:
输入T,,,,······,,要求输出,,,······,。
其中,。
分析:
可以暴力枚举a和b,但是效率不高。
考虑使用扩展欧几里得算法,枚举a,计算出,进而根据计算出b。有了a,b,,就可以在O(T)时间内计算出整个序列。如果在计算过程中发现和输入矛盾,则这个a是非法的。
那么如何根据扩展欧几里得算法计算出b呢?
根据扩展欧几里得算法,g=gcd(a,b),方程ax+by=g的一组解是(x0,y0),则当c是g的倍数时ax+by=c的一组解是(x0c/g,y0c/g);当c不是g的倍数时无整数解。
即:方程为
另外,计算c时可能溢出,因此使用long long。
代码:
#include<iostream>
using namespace std;
typedef long long ll;
int t;
ll a[10001],aa,b,d,x,y,c,m;
bool f;
void gcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b){
d=a;
x=1;
y=0;
}else{
gcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
int main(){
cin>>t;
for(int i=1;i<=2*t-1;i+=2){
cin>>a[i];
}
for(int i=0;i<=10000;i++){
f=true;
aa=i;
gcd(aa+1,10001,d,x,y);
c=a[3]-aa*aa*a[1];
if(c%d)
continue;
b=x*c/d;
b=(b%10001+10001)%10001;
for(ll j=2;j<=2*t&&f;j++){
m=(aa*a[j-1]+b)%10001;
if(j&1){
if(m!=a[j]){
f=false;
}
}else{
a[j]=m;
}
}
if(f)
break;
}
for(int i=2;i<=2*t;i+=2){
cout<<a[i]<<endl;
}
return 0;
}