2 条题解
-
0
20分超时:
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; bool v[N]; int main() { int n,m;scanf("%d%d",&n,&m); memset(v,0,sizeof(v)); int t=n,i=1,mi=0; while(t>1) { if(v[i]==0) { mi++; if(mi==m)mi=0,v[i]=1,t--; } i=i%n+1; } for(int i=1;i<=n;i++)if(v[i]==0){printf("%d\n",i); break;} return 0; }100分标程: /* 假设问题为:n个人(编号0~n-1),从编号为0的人开始报数1,报到k的人退出,剩下的人继续从1开始报数。求最后剩下的人的编号。 解析:我们知道第一个人(编号一定是m-1) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m的人开始):k k+1 k+2 ... n-2,n-1,0,1,2,... k-2。并且从k开始报1。 我们把他们的编号做一下转换:(k,k+1,k+2...n-1,0,1,...k-2)->(0,1,2,...n-1),转换后就成为了(n-1)个人报数的子问题。 假如我们知道这个子问题的解(设x是最终的胜利者),那么把这个x变回去不刚好就是n个人情况的解吗。变回去的公式很简单,相信大家都可以推出来:x'=(x+k) mod n。这显然就是一个倒推问题。下面写递推公式:令f表示i个人玩游戏报k退出最后胜利者的编号,最后的结果自然是f[n]. f[1]=0;f[i]=(f[i-1]+k) mod i (i>1) 最后结果是f[n],因为实际生活中编号总是从1开始,我们输出f[n]+1。 */
#include<bits/stdc++.h> using namespace std; int main() { int n,m,s=0;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)s=(s+m)%i; printf("%d\n",s+1); return 0; } -
0
20分超时:
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; bool v[N]; int main() { int n,m;scanf("%d%d",&n,&m); memset(v,0,sizeof(v)); int t=n,i=1,mi=0; while(t>1) { if(v[i]==0) { mi++; if(mi==m)mi=0,v[i]=1,t--; } i=i%n+1; } for(int i=1;i<=n;i++)if(v[i]==0){printf("%d\n",i); break;} return 0; }
100分标程:/* 假设问题为:n个人(编号0~n-1),从编号为0的人开始报数1,报到k的人退出,剩下的人继续从1开始报数。求最后剩下的人的编号。 解析:我们知道第一个人(编号一定是m-1) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m的人开始):k k+1 k+2 ... n-2,n-1,0,1,2,... k-2。并且从k开始报1。 我们把他们的编号做一下转换:(k,k+1,k+2...n-1,0,1, ...,k-2)->(0,1,2, ...,n-1),转换后就成为了(n-1)个人报数的子问题。 假如我们知道这个子问题的解(设x是最终的胜利者),那么把这个x变回去不刚好就是n个人情况的解吗。变回去的公式很简单,相信大家都可以推出来:x'=(x+k) mod n。这显然就是一个倒推问题。下面写递推公式:令f表示i个人玩游戏报k退出最后胜利者的编号,最后的结果自然是f[n]. f[1]=0;f[i]=(f[i-1]+k) mod i (i>1) 最后结果是f[n],因为实际生活中编号总是从1开始,我们输出f[n]+1。 */ #include<bits/stdc++.h> using namespace std; int main() { int n,m,s=0;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)s=(s+m)%i; printf("%d\n",s+1); return 0; }
- 1
信息
- ID
- 852
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 4
- 标签
- 递交数
- 66
- 已通过
- 33
- 上传者