BZOJ2976 : [Poi2002]出圈游戏
首先模拟一遍得到n个同余方程,然后用扩展欧几里得求出最小的可行解即可,时间复杂度$O(n^2)$。
#include<cstdio> #define N 30 int n,i,j,k,x,y,a[N],b[N],d[N],ans; namespace Solve{ int flag=1,k=1,m=0,d,x,y; int exgcd(int a,int b,int&x,int&y){ if(!b)return x=1,y=0,a; int d=exgcd(b,a%b,x,y),t=x; return x=y,y=t-a/b*y,d; } void add(int a,int r){ if(!flag)return; d=exgcd(k,a,x,y); if((r-m)%d){flag=0;return;} x=(x*(r-m)/d+a/d)%(a/d),y=k/d*a,m=((x*k+m)%y)%y; if(m<0)m+=y; k=y; } int ans(){ if(!flag)return 0; return m?m:k; } } int main(){ scanf("%d",&n); for(i=1;i<=n;i++)a[i]=i,scanf("%d",&x),b[x]=i; for(y=1,i=n;i>1;i--){ x=b[n-i+1]; Solve::add(i,((a[x]-a[y]+1)%i+i)%i); for(d[x]=1,k=0,j=1;j<=n;j++)if(!d[j])a[j]=++k; for(y=x;d[j];)if((++y)>n)y=1; } if(ans=Solve::ans())printf("%d",ans);else puts("NIE"); return 0; }