Joseph
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1768 Accepted Submission(s): 1095
Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.
這道題屬於一道比較經典的模擬題。但是如果方法選用不當,模擬的複雜度太高的話會導致TLE。。因此我們需要格外注意,降低模擬的複雜度。利用好取模的性質進行模擬。假設j是要數到的編號,那麼假設數到j這個數的人位置爲t,這個人被殺以後,我們需要進行的操作是將這個人後邊一直到末尾的編號都減1,相當於補充被殺的這個人的位置缺口。這時我們計算下一個被殺的人的位置。就是(t+j-1)%num(num表示總人數,這時的num是減去1之後的,因爲殺掉一個人num就要減1)。這個式子得出的位置結果就是下一個要被殺的人的位置。這個式子很巧妙。t是被殺的人的位置,而我們需要做的是將被殺的那個人之後的所有人的編號都減小1,那麼原先的(t+1)位置的人現在編號爲t,(t+2)位置的人現在爲(t+1),所以把當前的t位置當爲起始位置,以後的標號就爲0,1,2,3……j-1,總共j個人。所以用(t+j-1)%num就是下一個被殺人的位置。因而要掌握好這個式子表示的含義,也就能很方便的理解約瑟夫環的過程。這個式子比其他的模擬過程要簡潔的多,也可以較快的求出結果。
參考代碼:
#include<cstdio>
int a[15];
int main()
{
int n;
for(int i=1;i<=14;i++)
{
for(int j=i+1;;j++)
{
int num=2*i,t=j%num; //num表示總人數,t表示被殺人的位置
if(t==0) t=num;
int cnt=0;
while(t>i) //因爲要保證i+1~2*i的人先被殺,所以被殺人的編號t要始終大於i,如果不大於i,則退出循環,那麼被殺的人的個數也就達不到i
{
num--;
t=(t+j-1)%num;
if(t==0) t=num;
cnt++; //cnt表示被殺的人的個數
}
if(cnt==i)
{
a[i]=j;
break;
}
}
}
while(~scanf("%d",&n)&&n)
{
printf("%d\n",a[n]);
}
}