zoj--1088--System Overload

来源:互联网 发布:阿里云cdn多少钱 编辑:程序博客网 时间:2024/04/29 20:49

这道题开始一看还真没有什么思路,后面看了一下数据范围,数据不大

就直接暴力枚举求解了,最后也过了。

后来在网上查了一下,有人讲这是一个关于约瑟夫环的问题,就去看了一下约瑟夫环的相关知识

才发现是原来是有公式的。。。。。。。。。。。


下面是关于约瑟夫环问题的一篇文章的链接

http://blog.csdn.net/sunandice/article/details/6560889


代码如下:

第一个是直接枚举求解,第二个是公式法

//直接枚举m求解#include<iostream>using namespace std;int main(){    int a[155],n,i,b[155];    while(cin>>n&&n)    {         for(i=0;i<n;i++)         {            a[i]=i+1;            b[i]=a[i];         }         int m=1,sum,cnt,k;         while(1)         {             int flag=0;             sum=1; cnt=0; a[0]=0; k=1;             while(1)             {                 if(a[k])                   cnt++;                 if(cnt==m)                 {                    a[k]=0;                    sum++;                    cnt=0;                 }                 k=(k+1)%n;  //循环队列思想                 if(a[1]&&sum==n-1)                 {                    flag=1;                    break;                 }                 if(!a[1]&&sum<=n-1)                   break;             }             for(i=0;i<n;i++)//开始时没考虑到每一次模拟都会导致a[]变化                 a[i]=b[i];  //所以总是陷入死循环;b[]的作用就是每枚举一次m后重新恢复a[]的值             if(flag)             {               cout<<m<<endl;               break;             }             m++;        }    }  return 0;}

//问题二:求出最后出圈的那个人的序号//方法一:模拟,最后留下的元素就是所求元素//方法二:利用递推公式 f[1]=0 f(i)=f(f[i-1]+m)%i; #include<iostream>using namespace std;int n,m;bool judge(){    int from = 0;    for(int i = 2 ;i < n ; i ++)      from = (from + m)%i;    if(from + 1 == 1) return true;//最后剩下的那栋楼的最开始的编号是1的话,返回true    else return false;}int main(){     while(cin>>n&&n)     {         m=1;         while(!judge())              ++m;         cout<<m<<endl;     }  return 0;}


0 0