约瑟夫环(模板)
第一种题:(●ˇ∀ˇ●),
题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1073
①:最好理解的放法,但时间复杂度过高! 2187 ms 5616 KB
所参考博客:https://blog.csdn.net/kangroger/article/details/39254619
1 #include<stdio.h> 2 #include<cstring> 3 using namespace std; 4 int people[1000100];//表示人. 5 int main() 6 { 7 int n,m; 8 while (scanf("%d%d",&n,&m)!=EOF) 9 { 10 int cnt=0;//标记出列的有多少个 11 memset(people,1,sizeof(people)); 12 for (int i=1,j=0; ;i++)//j表示报数是多少 ,i表示第几个人 13 { 14 if (people[i])//表示i没出列 15 { 16 j++; 17 if (j==m)//如果报数和要求的数相同 18 { 19 ++cnt; 20 j=0;//初始 21 people[i]=0;//标记第i个人出列 22 } 23 if (cnt==n)//如果已经全部出列,那就结束 24 { 25 printf("%d\n",i); 26 break; 27 } 28 } 29 if (i==n) 30 { 31 i=0; 32 } 33 } 34 } 35 return 0; 36 }
②复杂度低的方法 31 ms 1708 KB 超级短小精悍!
1 #include <stdio.h> 2 int main() 3 { 4 int n, m, i, s = 0; 5 while (scanf("%d%d", &n, &m)!=EOF) 6 { 7 for (i = 2; i <= n; i++) 8 { 9 s = (s + m) % i; 10 } 11 printf ("%d\n", s+1); 12 } 13 }
③这应该是最厉害的了 时间更短
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int main(){ 7 unsigned long long i,j,n,k; 8 cin>>n>>k; 9 long long y=k%2; 10 long long x=2,t=0; 11 long long z1,z2; 12 z1=y; 13 z2=x; 14 while(x<=n){ 15 z1=y; 16 z2=x; 17 t=(x-y)/(k-1); 18 if(t==0) t++; 19 y=y+t*k-((y+t*k)/(x+t))*(x+t); 20 x+=t; 21 } 22 cout<<(z1+(n-z2)*k)%(n)+1<<endl; 23 }
第二种题:(●ˇ∀ˇ●)
根据第一种题改编,由于题目n小,所以可以用第一种题的“简单”方法。
题目链接:https://www.nowcoder.com/acm/contest/121/D
1 #include<stdio.h> 2 #include<cstring> 3 using namespace std; 4 int people[30];//表示人. 5 int main() 6 { 7 int n,m; 8 while (scanf("%d%d",&n,&m)!=EOF) 9 { 10 int cnt=0;//标记出列的有多少个 11 memset(people,1,sizeof(people)); 12 for (int i=1,j=0; ;i++)//j表示报数是多少 ,i表示第几个人 13 { 14 if (people[i])//表示i没出列 15 { 16 j++; 17 if (j==m)//如果报数和要求的数相同 18 { 19 ++cnt; 20 j=0;//初始 21 people[i]=0;//标记第i个人出列 22 if (cnt==1) 23 printf("%d",i); 24 else 25 printf(" %d",i); 26 } 27 if (cnt==n)//如果已经全部出列,那就结束 28 { 29 printf("\n"); 30 break; 31 } 32 } 33 if (i==n) 34 { 35 i=0; 36 } 37 } 38 } 39 return 0; 40 }