CCF遊戲C/C++【2018.3.17】
阿新 • • 發佈:2019-01-04
問題描述: 有n個小朋友圍成一圈玩遊戲,小朋友從1至n編號,2號小朋友坐在1號小朋友的順時針方向,3號小朋友坐在2號小朋友的順時針方向,……,1號小朋友坐在n號小朋友的順時針方向。
遊戲開始,從1號小朋友開始順時針報數,接下來每個小朋友的報數是上一個小朋友報的數加1。若一個小朋友報的數為k的倍數或其末位數(即數的個位)為k,則該小朋友被淘汰出局,不再參加以後的報數。當遊戲中只剩下一個小朋友時,該小朋友獲勝。
例如,當n=5, k=2時:
1號小朋友報數1;
2號小朋友報數2淘汰;
3號小朋友報數3;
4號小朋友報數4淘汰;
5號小朋友報數5;
1號小朋友報數6淘汰;
3號小朋友報數7;
5號小朋友報數8淘汰;
3號小朋友獲勝。
給定n 和k,請問最後獲勝的小朋友編號為多少?輸入格式 輸入一行,包括兩個整數n和k,意義如題目所述。輸出格式 輸出一行,包含一個整數,表示獲勝的小朋友編號。樣例輸入5 2樣例輸出3樣例輸入7 3樣例輸出4
遊戲開始,從1號小朋友開始順時針報數,接下來每個小朋友的報數是上一個小朋友報的數加1。若一個小朋友報的數為k的倍數或其末位數(即數的個位)為k,則該小朋友被淘汰出局,不再參加以後的報數。當遊戲中只剩下一個小朋友時,該小朋友獲勝。
例如,當n=5, k=2時:
1號小朋友報數1;
2號小朋友報數2淘汰;
3號小朋友報數3;
4號小朋友報數4淘汰;
5號小朋友報數5;
1號小朋友報數6淘汰;
3號小朋友報數7;
5號小朋友報數8淘汰;
3號小朋友獲勝。
給定n
輸出1(含錯誤及解決方案):
#include<stdio.h> #include<stdlib.h> //int bei(int x,int k); struct node { int data; struct node *next; }; //int mo(int x,int k); int main() { int n,k,i,x; struct node *head,*p,*q,*t; head=NULL; scanf("%d%d",&n,&k); for(i=0;i<n;i++){ x=i+1; p=(struct node *)malloc(sizeof(struct node)); p->data=x; p->next=NULL; if(head==NULL){ head=p; }else{ q->next=p; } q=p; } q->next=head; t=head; // t=t->next; // while(t->next!=head){ // printf("%d",t->data); // t=t->next; // } if(k==1) printf("%d",n); else{ int sum=1; while(t->next!=t){ // if(bei(sum,k)==1) //易犯錯誤:連跳兩步,第二輪會發生錯誤 // { // printf("%d\t",t->next->data); // t->next=t->next->next; // sum++; // } // if(mo(sum,k)==1){ //做的太複雜,被整數倍數整除等價於被該數整除 // printf("%d\t",t->next->data); // t->next=t->next->next; // sum++; // } // sum++; // t=t->next; // } // printf("%d",t->data); // if((sum+1)%k==0||(sum+1)%10==k){ t->next=t->next->next; sum++; } else{ t=t->next; sum++; } } printf("%d",t->data); } return 0; } //int bei(int x,int k) //{ // int n=1000,i; // for(i=1;i<n;i++){ // if((x+1)%(i*k)==0){ // return 1; // break; //// }else if(((x+1)%10)==k){ //// return 1; //// break; // }else return 0; // } //} //int mo(int x,int k) //{ // if((x+1)%10==k){ // return 1; // }else return 0; //}
輸出2(正確思路【迴圈連結串列方法】):
輸出3(簡易方法【C++佇列】):#include<stdio.h> #include<stdlib.h> struct node { int data; struct node *next; }; int main() { int n,k,i,x; struct node *head,*p,*q,*t; head=NULL; scanf("%d%d",&n,&k); for(i=0;i<n;i++){ x=i+1; p=(struct node *)malloc(sizeof(struct node)); p->data=x; p->next=NULL; if(head==NULL){ head=p; }else{ q->next=p; } q=p; } q->next=head; t=head; if(k==1) printf("%d",n); else{ int sum=1; while(t->next!=t){ if((sum+1)%k==0||(sum+1)%10==k){ t->next=t->next->next; sum++; } else{ t=t->next; sum++; } } printf("%d",t->data); } return 0; }
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
queue<int> q;
int main()
{
int n,k;
int sum=1;
cin>>n>>k;
if(k==1)
{
cout<<n<<endl;
return 0;
}
for(int i=1;i<=n;i++)
q.push(i);
while(q.size()!=1)
{
int tmp=q.front();
q.pop();
if(sum%k==0||sum%10==k)
{
sum++;
// cout<<tmp<<endl;
}
else
{
q.push(tmp);
sum++;
}
}
cout<<q.front();
return 0;
}
總結:
1、這是我見到的第一個真正意義上的難題(以前碰見難題都不怎麼做。。。),主要難在思路上轉不過彎來,由於知識體系不夠,只能用C的連結串列寫,故總是糾結於連結串列的刪除方法帶來的影響,其實只要在意那個記數變數sum的變化就夠了,不用那麼麻煩。
2、有些東西不需要函式考慮不要緊拉著函式進來,比如能被某個數的倍數整除就等價於對那個數取模等於零,不要想得太複雜,越複雜越容易錯。