0
点赞
收藏
分享

微信扫一扫

ht的生日party (递归 或 递推)

郝春妮 2023-12-30 阅读 35


题目链接:传送门

题目描述:

题目描述

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

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

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

       现在问谁是出来唱歌的人

 

 

输入

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

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

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

 

 

输出

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

 

 

样例输入 

2
2 3
1
6
2 4
1
6
 

样例输出:

1

4

1

5

题解,思路写在代码里面。

递归:

#include <iostream>
#include <cstring>
#include <cstdio>
 
using namespace std;
int n, m;
  
// 假设一个序列 一共 7人 A:  1, 2, 3, 4, 5, 6 ,7
// m = 3
 
// 第一次出列 队列只剩下5人:
// 1, 2, 4, 5, 7
// 因为第二次要从尾部开始数:
// 队列应为 B:  7, 5, 4, 2, 1
 
// BchangeintoA() 函数是将求得 "数组B中下标为 i的人" 在 "数组 A中的下标"
// 下标 从 1 开始 
// 例如 7, 在B中的下标为 1, 在A中下标为 7
// 例如 2, ............. 4, ........... 2 
// alen 数组A 的长度 
int BchangeintoA(int alen, int i, int blen) { 
    i = blen+1 - i;
    int temp = i + (i-1)/(m-1);
    return temp;
}
 
const int N = 1000100;
int F[N]; // F[N] 不为-1 则表示如果队列为N,唱歌的人的编号
// Example: F[2] = 1 , 如果序列长度为2,编号为1的 人唱歌
// 所有人下标从1开始
 
int Work(int num) {
    // 函数f 是去求解f[num],即队列中的人数 为num时唱歌的人的编号
    if(F[num] != -1) {
        return F[num]; 
    }
     
    if(num < m){
        F[num] = 1;
        return 1;
    }
 
    Work(num-num/m);
    // 减而治之,例如如果是 7 个人的队列,在数一遍之后只剩下五个人
 
    F[num] = BchangeintoA(num, F[num-num/m], num-num/m);
    // num >= m :  每一个F[num] 都是有 F[num-num/m] 推过来 
     
//    for(int i=1; i<=num; i++) {
//      cout << F[i] << " "; 
//  } 
//  cout << endl;
     
    return F[num];
}
 
int main(){
    int T;
    cin >> T;
    for(int t=1; t<=T; t++) {
        cin >> n >> m;
 
        memset(F, -1, sizeof(F)); // 对 f 进行初始化
         
        int x;
        for(int i=1; i<=n; i++) {
            scanf("%d",&x);
            printf("%d\n",Work(x));
        }
    }
    return 0;
}

递推:

#include <iostream>
#include <cstring>
#include <cstdio> 
using namespace std;
 
const int N = 1000100;
int F[N];
int n, m;
  
int BchangeintoA(int alen, int i, int blen) { 
    i = blen+1 - i;
    int temp = i + (i-1)/(m-1);
    return temp;
}
 
int main(){
    int T;
    cin >> T;
    for(int t=1; t<=T; t++) {
        cin >> n >> m;
 
        memset(F, -1, sizeof(F)); // 对 f 进行初始化
        for(int i=1; i<m; i++) {
            F[i] = 1;
        }
         
        int x;
        int max = m-1;
         
        for(int i=1; i<=n; i++) {
            scanf("%d",&x);
            if(x <= max) {
                printf("%d\n",F[x]);
            }
            else {
                for(int i=max+1; i<=x; i++) {
                    F[i] = BchangeintoA(i, F[i-i/m], i-i/m);
                }
                max = x;
                printf("%d\n",F[max]);
            }
//          for(int i=1; i<=max; i++){
//              printf("%d ",F[i]);
//          }
//          printf("\n");
        }
    }
    return 0;
}

 

举报

相关推荐

0 条评论