LA3882(約瑟夫問題及變形)
阿新 • • 發佈:2019-02-02
我相信大家早就瞭解了約瑟夫問題
如小學的 猴子選大王:一堆猴子都有編號,編號是1,2,3 ...m,這群猴子(m個)按照1-m的順序圍坐一圈,從第1開始數,每數到第N個,該猴子就要離開此圈,這樣依次下來,直到圈中只剩下最後一隻猴子,則該猴子為大王。
作為一道相當經典的題,還有一個使其更簡單的變式
題目大意:
N個數排成一圈,第一次刪除m,以後每k個數刪除一次,求最後一被刪除的數(即最後留下是的數,下面用“勝利者”來代指要求的數)
題解:
假設從0開始刪除第k個數,很顯然,第 k mod n個人背踢出,然後剩下的n-1個人組成一個新環,並且勝利者一定在中間)
k k+1 k+2 ... n-2,n-1,0,1,2,... k-2
並且從k開始報0。
我們把他們的編號做一下轉換:
k --> 0
k+1 --> 1
k+2 --> 2
...
k-2 --> n-2
接下來需要將勝利者的序號調整回來,這十分簡單:x'=(x+k) mod n
那麼我們如何在(n-1)個數中尋找勝利者呢?顯而易見,他一定在去掉第k mod n個人的(n-2)人中,再調整為0~n-2,然後不斷遞推
公式:
f[1]=0; f=(f+m) mod i; (i>1) 又因為m<>0,所以答案是ans=(m-k+1+f[n])%n,注意要處理ans<=0的情況(ans=ans+n)下面是程式碼:
#include<cstdio>
int main()
{
int n,m,k,f;
while(scanf("%d%d%d",&n,&k,&m)==3&&n)
{
f=0;
for(int i=2;i<=n;i++)f=(f+k)%i;
f=(m-k+1+f)%n;
if(f<=0)f+=n;
printf("%d\n",f);
}
}
因為不需要儲存f,所以不需陣列f[n],這樣可以大大的減小記憶體