hdu5643 King's Game(约瑟夫环+线段树)
生活随笔
收集整理的這篇文章主要介紹了
hdu5643 King's Game(约瑟夫环+线段树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Problem Description In order to remember history, King plans to play losephus problem in the parade gap.He calls?n(1≤n≤5000)?soldiers, counterclockwise in a circle, in label?1,2,3...n.
The first round, the first person with label?1?counts off, and the man who report number?1?is out.
The second round, the next person of the person who is out in the last round counts off, and the man who report number?2?is out.
The third round, the next person of the person who is out in the last round counts off, and the person who report number?3?is out.
The N - 1 round, the next person of the person who is out in the last round counts off, and the person who report number?n?1?is out.
And the last man is survivor. Do you know the label of the survivor?
Input The first line contains a number?T(0<T≤5000), the number of the testcases.
For each test case, there are only one line, containing one integer?n, representing the number of players.
Output Output exactly?T?lines. For each test case, print the label of the survivor.
Sample Input 2 2 3
Sample Output 2 2 Hint: For test case #1:the man who report number $1$ is the man with label $1$, so the man with label $2$ is survivor. For test case #1:the man who report number $1$ is the man with label $1$, so the man with label 1 is out. Again the the man with label 2 counts $1$, the man with label $3$ counts $2$, so the man who report number $2$ is the man with label $3$. At last the man with label $2$ is survivor. 題意:n個人排成一圈,每回合殺死一個人,殺死后從那個人的下一個人開始數數,第i個回合數到i的那個人被殺死,問最后剩下的人的編號是多少。 思路:這題和約瑟夫環有點像,我們設f[n]為總人數為n時,按照題目中的規則殺,最后剩下來的人的編號是多少。我們每次殺死一個人后就重新編號,那么f[1]=0,即當最后只剩下一個人時,他經過重新編號后新的編號為0,那么在上一輪,他的編號為t=(0+n-1)%2,倒數第二輪他的編號為(t+n-2)%3,這樣可以依次類推到f[n],就是答案了,所以這題只要用O(n^2)的復雜度初始化一下就行了。 這種方法有個缺陷,就是不能知道每一次殺死的人的編號是什么,如果要知道每一次殺死的人的編號,我們可以用線段樹做。我們在線段樹上對于每一段維護其剩余的空位數,那么我們每次計算這一次殺死的人是線段樹總區間的第幾個人,這樣就可以知道每次的編號是多少了,如果這題用線段樹,為了防超時,可以打個表。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<bitset> #include<algorithm> using namespace std; typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) #define maxn 6006 int a[maxn]; void init() {int i,j;a[1]=1;for(i=2;i<=5000;i++){int num=0;//for(j=i-1;j>=1;j--){for(j=1;j<=i;j++){num=(num+i-j+1)%j;}a[i]=num+1;} }int main() {int n,m,i,j,T;init();scanf("%d",&T);while(T--){scanf("%d",&n);printf("%d\n",a[n] );}return 0; }
下面的程序還要打個表再提交。 #include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<bitset> #include<algorithm> using namespace std; typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) #define maxn 5006 struct node{int l,r,num; }b[4*maxn];int n; void build(int l,int r,int th) {int mid;b[th].l=l;b[th].r=r;b[th].num=r-l+1;if(l==r)return;mid=(l+r)/2;build(l,mid,th*2);build(mid+1,r,th*2+1); }void update(int num,int cishu,int th) {int mid;if(b[th].l==b[th].r){b[th].num=0;if(cishu==n)printf("%d,",b[th].l);return;}if(b[th*2].num>=num){update(num,cishu,th*2);}else{update(num-b[th*2].num,cishu,th*2+1 );}b[th].num=b[th*2].num+b[th*2+1].num; }int main() {int t,m,i,j,T,k;freopen("o.txt","w",stdout);for(n=1;n<=5000;n++){build(1,n,1);int p=1;int tot=n;for(k=1;k<=n;k++){p=(p+k-1)%tot; //這里算這回合殺死的人的編號的空格數if(p==0)p=tot;update(p,k,1);if(p==tot)p=1; //這里算出這回合殺死人后,下一回合第一個數數的編號,也可以看做是下一回合站第幾個空位tot--; //每次總人數減1}} }
The first round, the first person with label?1?counts off, and the man who report number?1?is out.
The second round, the next person of the person who is out in the last round counts off, and the man who report number?2?is out.
The third round, the next person of the person who is out in the last round counts off, and the person who report number?3?is out.
The N - 1 round, the next person of the person who is out in the last round counts off, and the person who report number?n?1?is out.
And the last man is survivor. Do you know the label of the survivor?
Input The first line contains a number?T(0<T≤5000), the number of the testcases.
For each test case, there are only one line, containing one integer?n, representing the number of players.
Output Output exactly?T?lines. For each test case, print the label of the survivor.
Sample Input 2 2 3
Sample Output 2 2 Hint: For test case #1:the man who report number $1$ is the man with label $1$, so the man with label $2$ is survivor. For test case #1:the man who report number $1$ is the man with label $1$, so the man with label 1 is out. Again the the man with label 2 counts $1$, the man with label $3$ counts $2$, so the man who report number $2$ is the man with label $3$. At last the man with label $2$ is survivor. 題意:n個人排成一圈,每回合殺死一個人,殺死后從那個人的下一個人開始數數,第i個回合數到i的那個人被殺死,問最后剩下的人的編號是多少。 思路:這題和約瑟夫環有點像,我們設f[n]為總人數為n時,按照題目中的規則殺,最后剩下來的人的編號是多少。我們每次殺死一個人后就重新編號,那么f[1]=0,即當最后只剩下一個人時,他經過重新編號后新的編號為0,那么在上一輪,他的編號為t=(0+n-1)%2,倒數第二輪他的編號為(t+n-2)%3,這樣可以依次類推到f[n],就是答案了,所以這題只要用O(n^2)的復雜度初始化一下就行了。 這種方法有個缺陷,就是不能知道每一次殺死的人的編號是什么,如果要知道每一次殺死的人的編號,我們可以用線段樹做。我們在線段樹上對于每一段維護其剩余的空位數,那么我們每次計算這一次殺死的人是線段樹總區間的第幾個人,這樣就可以知道每次的編號是多少了,如果這題用線段樹,為了防超時,可以打個表。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<bitset> #include<algorithm> using namespace std; typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) #define maxn 6006 int a[maxn]; void init() {int i,j;a[1]=1;for(i=2;i<=5000;i++){int num=0;//for(j=i-1;j>=1;j--){for(j=1;j<=i;j++){num=(num+i-j+1)%j;}a[i]=num+1;} }int main() {int n,m,i,j,T;init();scanf("%d",&T);while(T--){scanf("%d",&n);printf("%d\n",a[n] );}return 0; }
下面的程序還要打個表再提交。 #include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<bitset> #include<algorithm> using namespace std; typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) #define maxn 5006 struct node{int l,r,num; }b[4*maxn];int n; void build(int l,int r,int th) {int mid;b[th].l=l;b[th].r=r;b[th].num=r-l+1;if(l==r)return;mid=(l+r)/2;build(l,mid,th*2);build(mid+1,r,th*2+1); }void update(int num,int cishu,int th) {int mid;if(b[th].l==b[th].r){b[th].num=0;if(cishu==n)printf("%d,",b[th].l);return;}if(b[th*2].num>=num){update(num,cishu,th*2);}else{update(num-b[th*2].num,cishu,th*2+1 );}b[th].num=b[th*2].num+b[th*2+1].num; }int main() {int t,m,i,j,T,k;freopen("o.txt","w",stdout);for(n=1;n<=5000;n++){build(1,n,1);int p=1;int tot=n;for(k=1;k<=n;k++){p=(p+k-1)%tot; //這里算這回合殺死的人的編號的空格數if(p==0)p=tot;update(p,k,1);if(p==tot)p=1; //這里算出這回合殺死人后,下一回合第一個數數的編號,也可以看做是下一回合站第幾個空位tot--; //每次總人數減1}} }
轉載于:https://www.cnblogs.com/herumw/p/9464516.html
總結
以上是生活随笔為你收集整理的hdu5643 King's Game(约瑟夫环+线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机访问PC网站自动跳转到手机网站代码
- 下一篇: Android初学:联系创建Activi