题目链接:https://vjudge.net/problem/UVA-12169
题意:已知 a,b,x1 范围[0,10000],且 xi=(a∗xi−1+b)%10001 ,给出输入 T,x1,x3,...,x2∗T−1 ,求出任意一个符合题意的序列 x2,x4,...,x2∗T 。
思路:
- 当T==1时,此时对a,b没有限制,可取a=b=0,得
x2=0 。 - 当T>=2时,此时输入至少有
x1,x3
,则有
x2=(a∗x1+b)%n
x3=(a∗x2+b)%n
两者联立消掉未知的 x2 ,得
x3=(a∗(ax1+b)%n+b)%n
=(a∗(ax1+b)+b)%n
=(a2x1+(a+1)b)%n
- 即:
x3≡a2x1+(a+1)b (mod n)
则 (a+1)b≡x3−a2x1 ,当我们枚举a的时候,则变为扩展欧几里得的常见应用——求解模线性方程ax≡b (mod n),解出b后,就可以检验a,b是否满足题意。 - 或者变为
a2x1+(a+1)b−ny=x3
则 (a+1)b+n(−y)=x3−a2x1 ,当我们枚举a的时候,则变为扩展欧几里得的常见应用——求解线性方程ax+by=c的一组整数解。
- 即:
x3≡a2x1+(a+1)b (mod n)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define FOR(i,k,n) for(int i=k;i<n;i++)
#define FORR(i,k,n) for(int i=k;i<=n;i++)
#define scan(a) scanf("%d",&a)
#define scann(a,b) scanf("%d%d",&a,&b)
#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mst(a,n) memset(a,n,sizeof(a))
#define ll long long
#define N 105
#define mod 10001
#define INF 0x3f3f3f3f
const double eps=1e-8;
const double pi=acos(-1.0);
int x[N];
int ex_gcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1; y=0;
return a;
}
int d=ex_gcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return d;
}
int cal(int a,int b,int c)
{
int x,y;
int gcd=ex_gcd(a,b,x,y);
if(c%gcd) return -1;
x*=c/gcd;
if(b<0) b=-b;
//b/=gcd;//添加或去掉这条语句,都可以AC
x=x%b;
if(x<0) x+=b;
return x;//得到%10001下的解
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
cin>>t;
for(int i=1;i<=t;i++)
cin>>x[i];
if(t==1) cout<<0<<endl;
else
{
for(int a=0;a<=10000;a++)
{
//cout<<(x[2]-a*a%mod*x[1]%mod)%mod<<endl;
int cc=(x[2]-a*a%mod*x[1]%mod)%mod;
if(cc<0) cc+=mod;
int b=cal(a+1,mod,cc);
if(b==-1) continue;
int flag=1;
for(int i=3;i<=t;i++)
{
if(x[i]!=(a*a%mod*x[i-1]%mod+a*b%mod+b)%mod)
{
flag=0;
break;
}
}
if(flag)
{
for(int i=1;i<=t;i++)
cout<<(a*x[i]+b)%mod<<endl;
break;
}
}
}
return 0;
}