題意:
輸入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;
}