2976: [Poi2002]出圈游戏
题目连接:
http://www.lydsy.com/JudgeOnline/problem.php?id=2976
Description
Input
中第一行有一个正整数n, 2 <= n <= 20,第二行有n 个整数其中第i个整数表示编号为i 的小朋友第i个出圈。
Output
求最小的K,如果不存在,则输出一个单词“NO”
Sample Input
4
1 4 2 3
Sample Output
5
Hint
题意
题解:
转化一下,其实就是模线性方程组,这个玩意儿用CRT怼一波就好了
然而BZOJ这道题不是输出NO,而是输出NIE
BC这道题却题面写错了,我比赛后才反应过来这道题的题意
sad……
代码是BZOJ的那道题代码,HDU的需要加上test,和 CA是SB这句话
代码
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 30;
long long Egcd (long long a, long long b, long long &x, long long &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
long long d, tp;
d = Egcd (b, a%b, x, y);
tp = x;
x = y;
y = tp - a/b*y;
return d;
}
long long CRT2 (long long b[], long long n[], int num)
{
int i;
bool flag = false;
long long n1 = n[0], n2, b1 = b[0], b2, bb, d, t, k, x, y;
for (i = 1; i < num; i++)
{
n2 = n[i], b2 = b[i];
bb = b2 - b1;
d = Egcd (n1, n2, x, y);
if (bb % d) //模线性解k1时发现无解
{
flag = true;
break;
}
k = bb / d * x; //相当于求上面所说的k1【模线性方程】
t = n2 / d;
if (t < 0) t = -t;
k = (k % t + t) % t; //相当于求上面的K`
b1 = b1 + n1*k;
n1 = n1 / d * n2;
}
if (flag)
return -1; //无解
return b1; //形成的解:b1, b1+n1, b1+2n1,..., b1+xni...
}
int vis[30];
long long b[M], n[M];
long long t, num, i, cc = 1;
pair<int,int>P[M];
int main()
{
scanf ("%d",&num);
for (i = 0; i < num; i++)
n[i]=num-i;
for (i = 0; i < num; i++)
{
scanf("%d",&P[i].first);
P[i].second = i;
}
sort(P,P+num);
int las = num-1;
for (i = 0; i < num; i++)
{
int x;x=P[i].second;
int ttt = 0;
while(1)
{
las++;
las%=num;
if(vis[las])continue;
if(las==x)
{
b[i]=ttt;
vis[las]=1;
break;
}
ttt++;
}
}
long long p = CRT2(b,n,num);
if(p==-1)printf("NIE\n");
else printf("%lld\n",p+1);
return 0;
}