题意:对于52张给出顺序的扑克牌,做n次操作,每次将L~R的牌抽出来放到最前面。询问最后的扑克牌顺序。
思路:方法很多,这里用判断循环节的方法。容易看出,对于任意一张牌,在52次操作中,必定会出现位置的重复。这就是循环节。对于r之后的牌,不受操作影响,故而顺序不变。对于r之前的牌,第i张牌经过一次操作,位置会变为(i+(r-l+1))%r。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int a[53],p[53],f[53];
int T,n,l,r,k,x,y;
scanf("%d",&T);
for(int t=1;t<=T;t++)
{
for(int i=1;i<=52;i++)
scanf("%d",&a[i]);
scanf("%d%d%d",&n,&l,&r);
printf("Case #%d:",t);
for(int i=r+1;i<=52;i++)
p[i]=a[i];
for(int i=1;i<=r;i++)
{
memset(f,-1,sizeof(f));
f[i]=0;
k=i;
for(int j=1;j<=52;j++)
{
k=(k+(r-l+1))%r;
if(f[k]==-1) f[k]=j;
else
{
x=j-f[k];
y=f[k];
break;
}
}
for(int j=1;j<=(n-y)%x;j++)
k=(k+(r-l+1))%r;
p[k]=a[i];
}
p[r]=p[0];
for(int i=1;i<=52;i++)
printf(" %d",p[i]);
printf("\n");
}
return 0;
}