USACO 作弊的发牌者
作弊的发牌者
贝茜正在与她的N-1(2 <= N <= 100)个朋友打牌。她们玩的牌一副为K(N <= K <= 100,000,K为N的倍数)张。所有牌中,一共有M(M = K / N)张“好牌”,其余的K - M张为“差牌”。贝茜是游戏的发牌者,很自然地,她想把所有好牌都留给自己。她热衷于获胜,即使为此必须采取一些不正当的手段。
在若干局游戏后,贝茜的朋友们开始怀疑贝茜在游戏中作弊,于是她们想了个对策:使用新的发牌规则。规则具体如下:
1. 贝茜把牌堆的最上面一张发给她右边的奶牛
2. 每当贝茜发完一张牌,她都得将牌堆顶部接下来的P(1 <= P <= 10)张牌
放到底部去(一般把这个操作称为切牌)
3. 然后,贝茜对逆时针方向的下一头奶牛重复上述的操作
贝茜绝望地认为,她再也不可能获胜了,于是她找到了你,希望你告诉她,将好牌放在初始牌堆的哪些位置,能够确保它们在发完牌后全集中到她手里。顺带说明一下,我们把牌堆顶的牌定义为1号牌,从上往下第二张定义为2号牌,依此类推。
输入格式:
第1行: 3个用空格隔开的整数:N、K,以及P
输出格式:
第1..M行: 每行输出一个正整数,表示贝茜应该在初始牌堆的这个位置放一张
好牌。所有的位置按升序输出。
样例输入:
3 9 2
样例输出:
3
7
8
输出说明:
贝茜选择在牌堆中初始位置3、7、8各放一张好牌,这样她能在发完牌后如
愿以偿地拿到所有的好牌。以下是对这场游戏的模拟,牌堆中的数字代表这张牌
在初始牌堆中的位置:
牌堆 奶牛1 奶牛2 贝茜
初始状态 1 2 3 4 5 6 7 8 9 - - - - - - - - -
将牌堆顶的牌[1号牌]发给奶牛1 2 3 4 5 6 7 8 9 1 - - - - - - - -
切牌(#1 of 2) 3 4 5 6 7 8 9 2 1 - - - - - - - -
切牌(#2 of 2) 4 5 6 7 8 9 2 3 1 - - - - - - - -
将牌堆顶的牌[4号牌]发给奶牛2 5 6 7 8 9 2 3 1 - - 4 - - - - -
切牌(#1 of 2) 6 7 8 9 2 3 5 1 - - 4 - - - - -
切牌(#2 of 2) 7 8 9 2 3 5 6 1 - - 4 - - - - -
将牌堆顶的牌[7号牌]发给贝茜 8 9 2 3 5 6 1 - - 4 - - 7 - -
切牌(#1 of 2) 9 2 3 5 6 8 1 - - 4 - - 7 - -
切牌(#2 of 2) 2 3 5 6 8 9 1 - - 4 - - 7 - -
将牌堆顶的牌[2号牌]发给奶牛1 3 5 6 8 9 1 2 - 4 - - 7 - -
切牌(#1 of 2) 5 6 8 9 3 1 2 - 4 - - 7 - -
切牌(#2 of 2) 6 8 9 3 5 1 2 - 4 - - 7 - -
将牌堆顶的牌[6号牌]发给奶牛2 8 9 3 5 1 2 - 4 6 - 7 - -
切牌(#1 of 2) 9 3 5 8 1 2 - 4 6 - 7 - -
切牌(#2 of 2) 3 5 8 9 1 2 - 4 6 - 7 - -
将牌堆顶的牌[3号牌]发给贝茜 5 8 9 1 2 - 4 6 - 7 3 -
切牌(#1 of 2) 8 9 5 1 2 - 4 6 - 7 3 -
切牌(#2 of 2) 9 5 8 1 2 - 4 6 - 7 3 -
将牌堆顶的牌[9号牌]发给奶牛1 5 8 1 2 9 4 6 - 7 3 -
切牌(#1 of 2) 8 5 1 2 9 4 6 - 7 3 -
切牌(#2 of 2) 5 8 1 2 9 4 6 - 7 3 -
将牌堆顶的牌[5号牌]发给奶牛2 8 1 2 9 4 6 5 7 3 -
切牌(#1 of 2) 8 1 2 9 4 6 5 7 3 -
切牌(#2 of 2) 8 1 2 9 4 6 5 7 3 -
将牌堆顶的牌[8号牌]发给贝茜 - 1 2 9 4 6 5 7 3 8
发牌结束后,贝茜拿到了牌堆中初始位置分别为3、7、8的牌。
题解:
嗯......为了练习静态链表,这道题使用了静态链表来写
不过用队列的话代码好像要少一半
然后就是模拟,发一次牌(删除一次),放p张到最后
#include<iostream> #include<iomanip> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define MAX 20000010 int n,k,p,sum,out[110000]={},top=0; struct QAQ { int data; int cur; }s[MAX]; void del()//删除第一个(发一次牌)(这里是直接更改s[0].cur指向下一位) { int temp=s[0].cur; s[0].cur=s[temp].cur; } void insert()//每次向后添加p个 { s[top].data=s[s[0].cur-1].data; s[top].cur=top+1; s[0].cur++; } int main() { cin>>n>>k>>p; sum=k/n; for(int i=0;i<k;i++) { s[i].data=i+1; s[i].cur=i+1; } top=k; for(int i=1;i<=sum;i++) { for(int j=1;j<=n;j++) { del(); for(int l=1;l<=p;l++) { insert(); top++; } if(j==n-1)//记录下此时将要删除(发牌给自己)的值,即为答案 out[i]=s[s[0].cur-1].data; } } sort(out+1,out+sum+1); for(int i=1;i<=sum;i++) cout<<out[i]<<' '; return 0; }