反约瑟夫问题 【数论】

本人水平有限,题解不到为处,请多多谅解

本蒟蒻谢谢大家观看

题目:

6162: 反约瑟夫问题

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 169  Solved: 74
[Submit][Status][Web Board]

Description

著名的约瑟夫问题是这样描述的:N个人排成一个圆圈,然后把这N个人按逆时针方向编号为1、2、…、N;随机产
生一个正整数M,然后从编号为1的人开始按逆时针计数,当某人计数为M的倍数时,该人出队;如此循环下去,直
到队列里只有一个人留下。你现在的任务是:对于输入文件的N和K,其中N为初始时约瑟夫圆圈中的人数,K为约瑟
夫问题中最后留下的人的编号;请你确定一个最小能发生这种结果的正整数M。

Input

为N和K,0<N≤1000

Output

为最小的正整数M。

Sample Input

10 5

Sample Output

2

HINT

根据上一篇递推公式,我们可以反推M

f[1] = 0;          //当一个人的时候,出队人员编号为0

f[n] = (f[n-1] + m)%n     //m表示每次数到该数的人出列,n表示当前序列的总人数

则f[j]=(f[j-1]+i)%j   //i表示每次数到该数的人出列,j表示当前序列的总人数

f[n]+1==K时(因为下标从0开始),我们就直接输出i即可

code:

 1 #include<bits/stdc++.h>
 2 #pragma GCC optimize(3)
 3 const int N=1e3+10;
 4 using namespace std;
 5 int n,m;
 6 int f[N];
 7 void inint(){
 8     freopen("josephus.in","r",stdin);
 9     freopen("josephus.out","w",stdout);
10 }
11 inline int read(){
12     int x=0,f=1;char ch=getchar();
13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
14     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
15     return x*f;
16 }
17 inline void write(int x)
18 {
19     if(x<0)x=-x,putchar('-');
20     if(x>9)write(x/10);
21     putchar(x%10+'0');
22 }
23 int main()
24 {
25     //inint();
26     n=read(),m=read();
27     for(int i=1;i;i++){
28         for(int j=1;j<=n;j++){
29             f[j]=(f[j-1]+i)%j;
30         }
31         if(f[n]+1==m){
32             printf("%d
",i);
33             break;
34         }
35     }
36     return 0;
37 }

因为我们要找一个最小的M,所以当满足上述条件是直接berak即可

原文地址:https://www.cnblogs.com/nlyzl/p/11798538.html