UVALive 3882--And Then There Was One+约瑟夫环问题变形

题目链接:点击进入

题目意思大概和约瑟夫环问题差不多,唯一的不同点在于起点改成了m;刚开始的时候我想直接链表模拟算了,但是后面一看,数据太大,就改用公式做了。约瑟夫环的公式是:f(n)=(f(n-1)+k)%n

,对于这个题起点为m,所以答案就会变成ans=(f(n)+m-k+1)%n;

ans有可能小于0,此时我们要给他加上一个n,ans+=n。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;

const int maxn=11000;
int a[maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    int n,m,k;
    while(scanf("%d%d%d",&n,&k,&m)!=EOF)
    {
        if(!m&&!n&&!k) break;
        a[1]=0;
        for(int i=2;i<=n;i++)
           a[i]=(a[i-1]+k)%i;
        int ans=(a[n]+m-k+1)%n;
        if(ans<=0) ans+=n;
        printf("%d\n",ans);
    }
  return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-17 14:31:23

UVALive 3882--And Then There Was One+约瑟夫环问题变形的相关文章

约瑟夫环的变形

问题描述: 输入一个由随机数组成的数列(数列中每个数均是大于0的整数,长度已知),和初始计数值m.从数列首位置开始计数,计数到m后,将数列该位置数值替换计数值m,并将数列该位置数值出列,然后从下一位置从新开始计数,直到数列所有数值出列为止.如果计数到达数列尾段,则返回数列首位置继续计数.请编程实现上述计数过程,同时输出数值出列的顺序. 比如:输入的随机数列为:3,1,2,4,初始计数值m=7,从数列首位置开始计数(数值3所在位置) 第一轮计数出列数字为2,计数值更新m=2,出列后数列为3,1,4

poj 2886 Who Gets the Most Candies?(线段树+约瑟夫环+反素数)

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9934   Accepted: 3050 Case Time Limit: 2000MS Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise o

UVALive - 3882 —— And Then There Was One

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11350 约瑟夫环问题 这道题问的是最后死的是那个数字,所以可以不需要模拟,直接通过递推来推出最后幸存的那个数字: 声明:这里我们将所有人的编号都减1.比如8个人的编号变为0~7 我们可以通过倒推的方式获得最后剩下那个人在最开始的编号. 假设,现在只剩最后一个数字,那么我们从它开始编号,那么因为只有它只身一人,所以就只好将它编号为0 那么它在上一轮的编号是多少呢? 通过

UVALive - 3882:And Then There Was One

约瑟夫环 f[i]表示有i个人先处理第k个人,最后被处理的人是谁 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define MAXN 10005 using namespace std; int f[MAXN]; int n,m,k; int main() { while(1){ scanf("%d%d%d",&n,&k

一个不简洁的约瑟夫环解法

约瑟夫环类似模型:已知有n个人,每次间隔k个人剔除一个,求最后一个剩余的. 此解法为变种,k最初为k-2,之后每次都加1. 例:n=5,k=3.从1开始,第一次间隔k-2=1,将3剔除,第二次间隔k-1=2,将1剔除.依此类推,直至剩余最后一个元素. 核心思路:将原列表复制多份横向展开,每次根据间隔获取被剔除的元素,同时将此元素存入一个剔除列表中.若被剔除元素不存在于剔除列表,则将其加入,若已存在,则顺势后移至从未加入剔除列表的元素,并将其加入.如此重复n-1次.面试遇到的题,当时只写了思路,没

ytu 1067: 顺序排号(约瑟夫环)

1067: 顺序排号Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 31  Solved: 16[Submit][Status][Web Board] Description 有n人围成一圈,顺序排号.从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位. Input 初始人数n Output 最后一人的初始编号 Sample Input 3 Sample Output 2 HINT Source freepro

约瑟夫环 C语言 单循环链表

/*---------约瑟夫环---------*/ /*---------问题描述---------*/ /*编号为1,2,-,n的n个人围坐一圈,每人持一个密码(正整数). 一开始任选一个正整数作为报数上限值m, 从第一个人开始自1开始顺序报数,报到m时停止. 报m的人出列,将他的密码作为新的m值,从他的下一个人开始重新从1报数, 如此下去,直至所有人全部出列为止.试设计一个程序求出列顺序.*/ /*---------问题分析---------*/ /*n个人围坐一圈,且不断有人出列,即频繁

循环单向链表(约瑟夫环)

#include <stdio.h> #include <stdlib.h> typedef struct List { int data; struct List *next; }List; //创建循环单向链表n为长度 List *list_create(int n) { List *head, *p; int i; head = (List *)malloc(sizeof(List)); p = head; p->data = 1; //创建第一个结点 for (i =

约瑟夫环问题

(约瑟夫环问题)有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那个人. package aiqiyi; import java.util.ArrayList; public class Main { public static int leftPerson(int n) { // 用list来保存n个人,序号为1~n ArrayList<Integer> list = new ArrayList<Integer>()