BZOJ2976:[POI2002]出圈游戏(exCRT)
Description
有编号从1到n的n个小朋友在玩一种出圈的游戏,编号为i+1的小朋友站在编号为i小朋友左边。编号为1的小朋友站在编号为n的小朋友左边。首先编号为1的小朋友开始报数,接着站在左边的小朋友顺序报数,直到数到某个数字K时就出圈。直到所有的小朋友都出圈,则游戏完毕。游戏过程如下图所示。
Input
第一行有一个正整数n, 2 <= n <= 20,第二行有n 个整数其中第i个整数表示编号为i 的小朋友第i个出圈。
Output
求最小的K,如果不存在,则输出一个单词“NIE”
Sample Input
4
1 4 2 3
1 4 2 3
Sample Output
5
Solution
exCRT比较裸的题了,注意特判一下答案为0的情况
应该会exCRT就会这个题了
应该会exCRT就会这个题了
还有我竟然因为爆int调了半天也可以说是很丢人了QAQ
我就知道应该直接用long long
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define N (1001) 5 using namespace std; 6 7 int n,x,q[N],m[N],a[N]; 8 bool vis[N]; 9 10 void exgcd(int a,int b,int &d,int &x,int &y) 11 { 12 if (!b){d=a; x=1; y=0; return;} 13 exgcd(b,a%b,d,y,x); y-=x*(a/b); 14 } 15 16 int exCRT() 17 { 18 int M=m[1],A=a[1],d,x,y,t; 19 for (int i=2; i<=n-1; ++i) 20 { 21 exgcd(M,m[i],d,x,y); 22 if ((a[i]-A)%d) return -1; 23 x*=(a[i]-A)/d; t=m[i]/d; x=(x%t+t)%t; 24 A=M*x+A; M=M/d*m[i]; A%=M; 25 } 26 A=(A%M+M)%M; 27 if (!A) A=M; 28 return A; 29 } 30 31 int main() 32 { 33 scanf("%d",&n); 34 for (int i=1; i<=n; ++i) 35 { 36 scanf("%d",&x); 37 q[x]=i; 38 } 39 40 int now=1,cnt=1; 41 for (int i=1; i<=n-1; ++i) 42 { 43 m[i]=n-i+1; 44 while (1) 45 { 46 if (vis[now]) 47 { 48 now=now%n+1; 49 continue; 50 } 51 if (now==q[i]) 52 { 53 a[i]=cnt; 54 vis[q[i]]=true; 55 cnt=1; 56 break; 57 } 58 ++cnt; 59 now=now%n+1; 60 } 61 } 62 63 int ans=exCRT(); 64 if (ans==-1) printf("NIE"); 65 else printf("%d",ans); 66 }