LA3882 约瑟夫数学递归法

首先,约瑟夫环的数学优化方法为:

为了讨论方便,先把问题稍微改变一下,并不影响原意:问题描述: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

n-1
--> n-1-k     0--> n-k

... ...
  

k-3 --> n-3   k-2 --> n-2

序列1: 1, 2, 3, 4, …, n-2, n-1, n

序列2: 1, 2, 3, 4, … k-1, k+1, …, n-2, n-1,
n

序列3: k+1, k+2, k+3, …, n-2, n-1, n, 1, 2,
3,…, k-2, k-1   

序列4:1, 2, 3, 4, …, 5, 6, 7, 8, …, n-2, n-1
  

变换后就完完全全成为了(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)。

那么本题就好写了。

题目大意,n个数围成一个环,从第m个数开始,每k个数删除一次,最后一个数是是多少。

代码:


 1 #include <stdio.h>
2 #include <string.h>
3 #include <iostream>
4 #include <algorithm>
5 using namespace std;
6
7 main()
8 {
9 int n, m, k, i, j, f[10005];
10 while(scanf("%d %d %d",&n,&k,&m)!=EOF)
11 {
12 if(n==0&&k==0&&m==0) break;
13 f[1]=0;
14 for(i=2;i<=n;i++)
15 f[i]=(f[i-1]+k)%i;
16
17 int ans=(m-k+1+f[n])%n;
18 if(ans<=0)
19 ans+=n;
20 printf("%d\n",ans);
21 }
22 }

LA3882 约瑟夫数学递归法,布布扣,bubuko.com

时间: 2024-12-26 11:53:47

LA3882 约瑟夫数学递归法的相关文章

用递归法计算斐波那契数列的第n项

   斐波纳契数列(Fibonacci Sequence)又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.--在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)在现代物理.准晶体结构.化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1960年代起出版了<斐波纳契数列>季刊,专门刊载这方面的研究成果. [Fibonacci.cpp] #include<iostream>#

递归法

递归法(Recursion)是一种在函数或方法中调用自身的编程技术,在计算机方法中,使用递归技术往往使函数的定义和算法的描述简洁且易于理解.任何可以用计算机求解的问题所需要的计算时间都与其规模有关.而且规模越小,解题所需要的计算时间通常越小,从而比较容易处理. 简而言之,递归思想就是用与自身问题相似但规模较小的问题来描述自己. 例如,兔子出生两个月后就有繁殖能力,一对兔子每个月能生出一对兔子来.如果所有兔子都不死,那么一年以后可以繁殖多少对兔子? 第一个月小兔子没有繁殖能力,所有还是一对:两个月

002-算法-递归法

一.概念:(Recursion)在数学与计算机科学中,是指在函数定义中使函数自身的方法. 定义: 在数学和计算器及科学中,递归是指由一种(或多种)简单的基本情况定义的一类对象或方法,并规定其它所有情况都能被还原为其基本情况. http://zh.wikipedia.org/zh/%E9%80%92%E5%BD%92 eg:递归求n的阶乘 code: 1 /** 2 * @declare: 递归求N的阶乘<br> 3 * @author: cphmvp 4 * @version: 1.0 5 *

递归法的理解——以反转链表为例

2020-01-07 递归是什么: 递归,从定义上说,指的是某个函数直接或者间接调用自己时,则发生了递归. 比如说著名的斐波拉契数列的实现方法之一: 1 public static int f(int n){ 2 3 if(n == 1 || n == 2) return 1; 4 5 return f(n-1) + f(n-2); 6 7 } 在这个例子中,对于n大于2的情况,我们都直接调用f自身来递归解决了这个问题. 从底层的情况来思考,实际上计算机将相关的函数先压入stack中,然后再po

谭浩强 c程序设计 8.17用递归法将一个整数n转换成字符串。例如,输入486,应输出字符串&quot;486&quot;。n的位数不确定,可以是任意位数的整数。

8.17用递归法将一个整数n转换成字符串.例如,输入486,应输出字符串"486".n的位数不确定,可以是任意位数的整数. #include <stdio.h> char str1[20];int i=0;long n;int main(){        int longToStr(long n);    char *revstr(char *str, int len);    printf("请输入一个整数n:\n");    scanf("

2.简单求和[递归法]

计算1+2+3+4+5,用递归法的两种形式,练习这题主要查看递归规律,训练递归,形成递归的[本能].第一种,从后往前加. int sum(int a[],int n) { return n==0?0:sum(a,n-1)+a[n-1]; } 第二种,从两边对加,例:(1+5)+(2+4)+3,这个需要判定,假如数组的个数为偶,则左边+1==右边,如果为奇数,则左边+2==右边,需要将这三个数之和返回: int sum(int a[],int l,int r) { if(l+2==r)/*中间隔一

C语言之函数调用13—递归法求N阶勒让德多项式的值

//递归法! /* ======================================================= n阶勒让德多项式,n=1时,Pn(x)=x;n>=1时, Pn(x)=((2n-1)x-Pn-1(x)-(n-1)Pn-2(x))/2. ======================================================= */ #include <stdio.h> #include <math.h> double p(

C语言之函数调用14—递归法打印勒让德多项式前N项

//递归法 /* ================================================================== 题目:勒让德多项式 ================================================================== */ #include <stdio.h> double p(int n,double x) { if(n==0)return 1.0; else if(n==1)return x; else

C语言之函数调用16—递归法之一般函数的调用

//递归法 /* ================================================================== 题目:F(x,1)=1 F(x,n)=F(2x+1,n-1)*x  (n>1) ================================================================== */ #include<stdio.h> double F(float x,int n) { if(n==1) return