UVa LA 3882 - And Then There Was One 递推,动态规划 难度: 2

题目

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1883


题意

共有n个数(1..n)围成一个首尾相接的环,从m开始删除,每隔k个删除,最后留下来的是几?

 

思路

如刘书,首先是要找到递推关系。

1. 把起点视作编号0,f[n]为还剩下n个数(编号当然是紧挨的)的时候留下的最后一个编号,那么,明显f[n]与f[n - 1]有关系

2. 具体有什么关系呢?f[n]剩下的最后一个元素对应n个编号,删除第0个,重新以第k个编号为新起点的n-1个元素对应的f[n - 1],对应到公式上为(f[i - 1] + k - 1) % (i - 1) + 1

3. 现在不是从0开始,而是从m开始,也就是说最后还存在一个关系为:编号j的元素对应的值为(j + m - 1) % n + 1 

感想

1. 和刘汝佳的算的不一致,不太理解刘书怎么算的,也许定义方式略有不同?

 

代码

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <tuple>
#define LOCAL_DEBUG
using namespace std;
const int MAXN = 1e4 + 4;
int f[MAXN];

int main() {
#ifdef LOCAL_DEBUG
    freopen("C:\\Users\\Iris\\source\\repos\\ACM\\ACM\\input.txt", "r", stdin);
    //freopen("C:\\Users\\Iris\\source\\repos\\ACM\\ACM\\output.txt", "w", stdout);
#endif // LOCAL_DEBUG
    //int T;
//    scanf("%d", &T);
    int n, k, m;
    for (int ti = 1;scanf("%d%d%d", &n, &k, &m) == 3 && n; ti++) {
        f[1] = 0;
        for (int i = 2; i <= n; i++) {
            f[i] = (f[i - 1] + k - 1) % (i - 1) + 1;
        }
        int ans = (m - 1 + f[n]) % n;
        printf("%d\n", ans + 1);
    }

    return 0;
}
View Code

 

posted @ 2019-02-22 16:51  雪溯  阅读(103)  评论(0编辑  收藏  举报