UVA 151 - Power Crisis

Power Crisis 

During the power crisis in New Zealand this winter (caused by a shortage of rain and hence low levels in the hydro dams), a contingency scheme was developed to turn off the power to areas of the country in a systematic, totally fair, manner. The country was divided up into N regions (Auckland was region number 1, and Wellington number 13). A number, m, would be picked `at random', and the power would first be turned off in region 1 (clearly the fairest starting point) and then in every m'th region after that, wrapping around to 1 after N, and ignoring regions already turned off. For example, if N = 17 and m = 5, power would be turned off to the regions in the order:1,6,11,16,5,12,2,9,17,10,4,15,14,3,8,13,7.

The problem is that it is clearly fairest to turn off Wellington last (after all, that is where the Electricity headquarters are), so for a given N, the `random' number m needs to be carefully chosen so that region 13 is the last region selected.

Write a program that will read in the number of regions and then determine the smallest number m that will ensure that Wellington (region 13) can function while the rest of the country is blacked out.

Input and Output

Input will consist of a series of lines, each line containing the number of regions (N) with tex2html_wrap_inline42 . The file will be terminated by a line consisting of a single 0.

Output will consist of a series of lines, one for each line of the input. Each line will consist of the number m according to the above scheme.

Sample input

   
   
17
0

Sample output

7
典型的约瑟夫环
这里引用百度百科的公式推导过程
问题描述:n个人(编号0~(n-1)),从0开始报数,报到m-1的退出
,剩下的人继续从0开始报数。求胜利者的编号。
我们知道第一个人(编号一定是(m-1)%n) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m%n的人开始):
k k+1 k+2 ... n-2,n-1,0,1,2,... k-2
并且从k开始报0。
现在我们把他们的编号做一下转换:
k --> 0
k+1 --> 1
k+2 --> 2
...
...
k-3 --> n-3
k-2 --> n-2
序列1:0,1,2,3 … n-2,n-1
序列2:0,1,2,3 … k-2,k,…,n-2,n-1
序列3:k,k+1,k+2,k+3,…,n-2,n-1,0,1,2,3,…,k-2,
序列4:0,1,2,3 …,5,6,7,8,…,n-3,n-2
变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x是最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗?!!变回去的公式很简单,相信大家都可以推出来:
∵ k=m%n;
∴ x' = x+k = x+ m%n ; 而 x+ m%n 可能大于n
∴x'= (x+ m%n)%n = (x+m)%n
得到 x‘=(x+m)%n
如何知道(n-1)个人报数的问题的解?对,只要知道(n-2)个人的解就行了。(n-2)个人的解呢?当然是先求(n-3)的情况 ---- 这显然就是一个倒推问题!好了,思路出来了,下面写递推公式:
令f表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n].
递推公式:
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1)

#include<cstdio>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
#include <cstring>
#include <queue>
using namespace std;
#define eps 1e-20
#define MAXN 100000 + 10
#define outstars cout << "*********" << endl;
int n , m;
int work(int m)
{
    int i , a = 0;
    for(i = 2 ; i < n ; i++)
    {
        a = (a + m) % i;
    }
    return a;
}
int main()
{
    int t , i;

    while(scanf("%d",&n)!=EOF)
    {
        if(n == 0)break;
        for(i = 0 ; (t = work(i))!= 11 ; i++);
        printf("%d\n",i);
    }
    return 0;
}
/*

*/

t为什么要等于11呢,因为13个人从0到12,而第n - 1个人就是11.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值