题解:P12952 [GCJ Farewell Round #2] Intruder Outsmarting
题目传送门
题目分析
注意到,首先,转动转轮的过程实际上就是加
由上面两点不难看出,题目实际上是要求下面同余方程的解:
其中
上面的同余方程变形得
这是一个二元一次不定方程。根据裴蜀定理,有解的充分必要条件是
若有解,则使用扩展欧几里得算法求出方程的一组解。设
由于转动第
由于扩展欧几里得算法求出的解有正有负,因此需要分类讨论。
若
若
因此,只需取最小非负整数解和最大负整数解的相反数中较小值即可。
对于不定方程
综上,对于第
代码
#include<bits/stdc++.h>
#define N 2001
using namespace std;
long long x,y;
long long gcd(long long a,long long b){
if(b==0){
return a;
}
return gcd(b,a%b);
}
void exgcd(long long a,long long b){
if(b==0){
x=1;
y=0;
return;
}
exgcd(b,a%b);
long long t=x;
x=y;
y=t-a/b*y;
}
long long ans=0;
long long a[N];
int main(){
int t;
cin>>t;
for(int o=1;o<=t;o++){
ans=0;
cout<<"Case #"<<o<<": ";
int w,yes=1;
long long n,d;
cin>>w>>n>>d;
for(int i=1;i<=w;i++){
cin>>a[i];
}
long long g0=gcd(n,d);
for(int i=1;i<=w/2;i++){
if((a[i]-a[w-i+1])%g0!=0){
yes=0;
cout<<"IMPOSSIBLE"<<endl;
break;
}
exgcd(d,n);
long long n0=n/g0;
x=x*(((a[w-i+1]-a[i])/g0)%n0)%n0;
//cout<<x<<" "<<y<<endl;
//int nas0=ans;
if(x>=0){
x%=n0;
ans+=min(x,n0-x);
}
else{
long long x0=x+n0*(ceil((double)(-x)/(double)n0));
//cout<<x0<<endl;
ans+=min(x0,n0-x0);
}
//cout<<ans-nas0<<endl;
}
if(yes){
cout<<ans<<endl;
}
}
return 0;
}