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

Sample Output

5
 

Solution

exCRT比较裸的题了,注意特判一下答案为0的情况
应该会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 }
posted @ 2018-06-26 17:23  Refun  阅读(308)  评论(0编辑  收藏  举报