2 条题解

  • 0
    @ 2025-10-8 16:54:21

    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
      @ 2025-10-8 16:54:11

      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
      上传者