例題4 3 救濟金發放

2021-08-31 01:41:15 字數 1634 閱讀 7139

題目:

n(n<20)個人站成一圈,逆時針編號為1~n。 有兩個**,a從1開始逆時針數,b從n開始順時針數。 在每一輪中,**a數k個就停下來,**b數m個就停下來(注意有可能兩個**停在同乙個人上)。 接下來被**選中的人(1個或者2個)離開隊伍。輸入n,k,m輸出每輪裡被選中的人的編號(如果有兩個人,先輸出被a選中的)。 例如,n=10,k=4,m=3,輸出為4 8, 9 5, 3 1, 2 6, 10, 7。 注意:輸出的每個數應當恰好佔3列。

解析:

注意題目的描述及示例,可以看出:要想經過1號,就要從n號開始逆時針走;要想經過n號,就要從1號開始順時針走;因此有:p1=n;p2=1;

圖示如下:

對於環狀問題,首先想到的就是求餘的方法,假設起始點為p,那麼每移動乙個點的原始的寫法是:

p=(p+1)%n;   //逆時針

p=(p-1)%n; //順時針

這樣寫有沒有問題呢?我們需要考慮邊界條件。分為兩種情況:

1.當逆時針移動時,考慮到n對n求餘等於0的時候(因為圈內沒有為0的點),此時p=(n-1);對應上面的示範為n=9。我們希望下乙個元素求餘等於10----這顯然是不可能的,因為乙個數對n求餘,其結果x一定滿足:0<=x<=(n-1)

如何解決這個問題呢?不妨讓求餘結果為(n-1),最終結果再加上1,就可以達到n了。

其實也就是用當前的值減一再對n進行求餘,最終結果+1。表示式:

p=(p+d-1)%n+1;	//其中d代表正一或負一(順時針或者逆時針走)
2.當順時針移動時,仍然考慮邊界條件。當p=1時,移動後的下乙個值應該到了10 。可是帶入資料卻發現餘數為0 。回顧逆時針的情況,最終的結果可以由餘9加1得到,餘9顯然在p=n-1時成立,因此表示式為:

p=(p+d+n-1)%n+1;
觀察上面兩個表示式,發現他們的差別僅僅是d的符號不同–這可以用傳不同引數來改變,以及差了乙個週期n–對於求餘來說,加減n的倍數最終的結果是不改變的。

**:

#include#include#include#include#include#include#include#define maxn 10000

using namespace std;

int n, k, m, a[maxn];

int go(int p,int d,int t)

while (a[p] == 0); //跳到非零的地方

} return p;

}int main()

a[p1] = a[p2] = 0;

if (left) printf(",");

} printf("\n");

} system("pause");

return 0;

}

救濟金發放

題目 n n 20 個人站成一圈,逆時針編號為1 n。有兩個 a從1開始逆時針數,b從n開始順時針數。在每一輪中,a數k個就停下來,b數m個就停下來 注意有可能兩個 停在同乙個人上 接下來被 選中的人 1個或者2個 離開隊伍。輸入n,k,m輸出每輪裡被選中的人的編號 如果有兩個人,先輸出被a選中的 ...

救濟金發放

n n 20 個人站成一圈,逆時針編號為1 n。有兩個 a從1開始逆時針數,b從n開始順時針數。在每一輪中,a數k個就停下來,b數m個就停下來 注意有可能兩個 停在同乙個人上 接下來被 選中的人 1個或者2個 離開隊伍。輸入n,k,m輸出每輪裡被選中的人的編號 如果有兩個人,先輸出被a選中的 例如,...

救濟金發放

前言 這個問題琢磨了挺長時間,發現裡面有很多需要考慮和注意的 問題描述 n n 20 個人站成一圈,逆時針編號為1 n。有兩個 a從1開始逆時針數,b從n開始順時針數。在每一輪中,a數k個就停下來,b數m個就停下來 注意有可能兩個 停在同乙個人上 接下來被 選中的人 1個或者2個 離開隊伍。輸入n,...