2136: ht的生日party(递推)@

2136: ht的生日party

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 83   Solved: 6

Submit Status Web Board

Description

 即使tmk上了大学,tmk还是十分怀念以前的高中生活还有以前的小伙伴们。

       Tmk还记得在高考前几天,tmk和他的小伙伴们参加了ht的生日party。在某个时间点,需要选出一个唱歌的人,于是tmk提议说不如我们来玩一次约瑟夫问题吧。

       我们有n个人排成一列,首先从头到尾报数1,2,3…..n,报到m的倍数的人出列,接下来从尾到头报数,报到m的倍数的人出列。直到人数小于m,这时再报一次数,报到1的人就被选出来唱歌。

       现在问谁是出来唱歌的人

 

Input

首先第一个数T,T<=10,表示数据组数。

每组数据,第一行有两个数,n和m(1<=n<=10000,1<m<=1000000),分别表示询问数和题目中的m

接下来有n行,每行一个数x(1<x<=1000000),表示一个询问,即问x个人排成一列,原编号为多少的人会被选出来唱歌。

 

Output

对于每组数据,输出n行,每行一个整数,第i行的整数表示第i个询问的答案

 

Sample Input

2
2 3
1
6
2 4
1
6

Sample Output

1
4
1
5

HINT

Source

【分析】先举一些例子,当有 10 个人,数 3 个人就出队我们只要找到小一点的每个数和当前数对应关系是什么就可以了例如上图,假设你下一轮 7 个人最后是第 5 个人存活的,那么 10 个人最后是第 4 个同学存活的,你如果下一轮 7 个人最后是第 1 个人存活的,那么 10 个人最后是第 10 个同学存活的,现在就是要找 C 数组和 A 数组的对应关系从 C 数组先推到 B 数组,再从 B 数组推到 A 数组设 A 数组的个数为 n,那么 B 数组和 C 数组就有 n-n/m 个数(/为整除)A[i]=B[i]+(B[i]-1)/(m-1)C[i]=B[(n-n/m)+1-i]这样就很容易得到这 C 和 A 的关系设 f[n]表示 n 个人玩游戏,幸存者为第 f[n]个人所以得到递推式复杂度就是 O(n)的

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+7;
typedef long long LL;
int f[N];
int n, m;
int dfs(int x)
{
    if(f[x]!=-1) return f[x];
    if(x<m)
    {
        f[x]=1;
        return 1;
    }
    int cnt=dfs(x-x/m);
    int ans=x-x/m-cnt+1+(x-x/m-cnt)/(m-1);
    f[x]=ans;
    return ans;
 }

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d %d",&n, &m);
        memset(f,-1,sizeof(f));
        while(n--)
        {
            int x;
            scanf("%d", &x);
            printf("%d\n",dfs(x));
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值