1 7 7 6 5 4 3 2 1
420
考虑对给定的出圈序列进行一次模拟,对于出圈的人我们显然可以由位置,编号等关系得到一个同余方程 一圈做下来我们就得到了n个同余方程 对每个方程用扩展欧几里得求解,最后找到最小可行解就是答案. 当然不要忘了判无解的情况.
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <set> #include <map> #include <queue> #include <stack> using namespace std; const int MAXN = 107; int num[MAXN]; long long mod[MAXN],b[MAXN]; // k(%mod)==b bool vis[MAXN]; void egcd(long long a, long long b, long long &d, long long &x, long long &y) { if (!b)d=a,x=1,y=0; else { egcd(b, a%b, d, y, x); y -= x*(a / b); } } long long CRT(int n) { long long M=mod[1],B=b[1],x,y,d; for (int i=2; i<=n; i++) { egcd(M,mod[i],d,x,y); if ((b[i]-B)%d)return -1; x=(b[i]-B)/d*x%(mod[i]/d); B+=x*M; M=M/d*mod[i]; B%=M; } return (B+M)%M?(B+M)%M:M; } int main() { int T; cin>>T; while(T--) { int n,p; memset(vis,0,sizeof(vis)); scanf("%d",&n); for(int i=1; i<=n; ++i) { scanf("%d",&p); num[p]=i; } int j=1,k; for(int i=1; i<=n; ++i) { k=1; while(j!=num[i]) { if(!vis[j])++k; j=j%n+1; } vis[num[i]]=1; mod[i]=n-i+1; b[i]=k%mod[i]; } int flag=CRT(n); if(flag==-1)cout<<"Creation August is a SB!\n"; else cout<<flag<<endl; } return 0; }
HDU-5668-Circle(中国余数定理/解同余方程组)
原文:http://blog.csdn.net/qq978874169/article/details/51253717