Circle
Problem Description
Satiya August is in charge of souls.
He finds n souls,and lets them become a circle.He ordered them to play Joseph Games.The souls will count off from the soul 1.The soul who is numbered k will be taken out,and will not join in the game again.
Now Satiya August has got the sequence in the Out Ordered,and ask you the smallest k.If you cannot give him a correct answer,he will kill you!
Input
The first line has a number T,means testcase number.
Each test,first line has a number n.
The second line has n numbers,which are the sequence in the Out Ordered**(The person who is out at aith round was numbered i)**.
The sequence input must be a permutation from 1 to n.
1≤T≤10,2≤n≤20.
Output
For each case,If there is a eligible number k,output the smallest k,otherwise,output”Creation August is a SB!”.
Sample Input
1
7
7 6 5 4 3 2 1
Sample Output
420
题意
编号1~n的n个人玩约瑟夫环,第k个人淘汰。n个人乱序排列,找到最小的k,使被淘汰的人编号按升序排列。
题解:
初始顺序为b,求出其最少需要报a[i]个数,才能淘汰i号。问题就转化为:
求最小的k,满足:
k
%
m
i
=
a
i
k \% m_i = a_i
k%mi=ai
m
i
m_i
mi依次为
n
,
n
−
1
,
.
.
.
,
1
n,n-1,...,1
n,n−1,...,1,
m
i
m_i
mi之间可能不互素,使用扩展中国剩余定理求出最小的k即可。
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<ctime>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 28;
const int mod = 1000000007;
LL a[maxn], m[maxn];
int b[maxn], vis[maxn];
LL exCRT(int n);
LL exgcd(LL a, LL b, LL &x, LL &y);
int main()
{
int n, i, j, k, t;
scanf("%d", &t);
while(t--)
{
memset(vis, 0, sizeof(vis));
memset(a, 0, sizeof(a));
scanf("%d", &n);
for(i=0;i<n;i++)
scanf("%d", &b[i]);
for(i=0;i<n;i++)
m[i] = n-i;
int pos = 0;
a[0] = 1;
for(i=0;i<n;i++){
while(b[pos] != i+1){
pos++;
if(pos>=n)pos-=n;
while(vis[pos]){
pos++;
if(pos>=n)pos -= n;
}
a[i]++;
}
a[i] %= n-i;
vis[pos] = 1;
}
LL ans = exCRT(n);
if(ans == 0)ans = m[0];
if(ans == -1)printf("Creation August is a SB!\n");
else printf("%lld\n", ans);
}
return 0;
}
LL exgcd(LL a, LL b, LL &x, LL &y)
{
if(b == 0)
{
x = 1, y = 0;
return a;
}
LL d = exgcd(b, a%b, y, x);
y -= x*(a/b);
return d;
}
LL exCRT(int n)
{
for(int i=1;i<n;i++)
{
LL c, e, x, y;
c = exgcd(m[0], m[i], x, y);
e = (a[i]-a[0]%m[i]+m[i])%m[i];
if(e%c == 0)
{
x = e/c*x%m[i];
while(x<0)x += m[i]/c;
a[0] += m[0]*x;
m[0] = m[0]/c*m[i];
a[0] = (a[0]%m[0]+m[0])%m[0];
}
else
return -1;
}
return a[0];
}