hdu 5643 (约瑟夫环加强版)

暴力打表法与递归实现约瑟夫环算法
本文介绍了两种解决约瑟夫环问题的方法:暴力打表法和递归实现。通过实例代码解释了每种方法的原理和实现过程,包括循环链表的使用和递归技巧的应用。

@(E ACMer)


一.循环链表暴力打表法:

在比赛中竟然没有调试正确,把函数里面分配的局部变量来作为链表的内容了显然函数一结束这块内存就被回收了.

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
typedef long long ull;
typedef long long ll;
typedef vector<int> vi;
#define xx first
#define yy second
#define rep(i, a, n) for (int i = a; i < n; i++)
#define sa(n) scanf("%d", &(n))
#define vep(c) for(decltype((c).begin()) it = (c).begin(); it != (c).end(); it++)
const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 12;


int cnt;

struct node {
    node* nexts, *lasts;
    int v;
}*p;


void moves(int x) {
    while (x) {
        p = p -> nexts;
        x--;
    }
}

void get(int n) {
    node* cur = new node;
    cur -> v = 1;
    p = cur;

    for (int i = 2; i <= n; i++) {
        node* temp = new node;
        temp -> v = i;
        p -> nexts = temp;
        temp -> lasts = p;
        p = temp;
    }
    p -> nexts = cur;
    cur -> lasts = p;
    p = cur;
    return;
}

void del(void) {
    node *lastnode = p -> lasts, *nextnode = p -> nexts;
    lastnode -> nexts = nextnode;
    nextnode -> lasts = lastnode;
    p = nextnode;
}



int main(void)
{
    freopen("a.txt", "w", stdout);
    int T = 5000;
    //cin >> T;
    int n = -1;
    while (n++, T--) {

        //cin >> n;
        get(n);
        /*
        rep (i, 0, n + n) {
             cout << p -> v << endl;
             moves(1);
        }*/
        for (int i = 1; i <= n - 1; i++) {
            moves(i - 1);
            del();
        }
        printf(",%d\n", p -> v);
    }
    return 0;
}

二.递归实现约瑟夫环

  • f(n,k) 表示长度为 n 的序列选择第k个数拿出去,最后剩下的那个数在本序列中的第 f(n,k) 个.
  • 让我们来想一下递推
  • 显然 f(1,k)==0 ,因为最后只剩下头一个

观察发现:

f(n,k)=(f(n1,k1)+k2) % n

code:

int ysf(int n, int k) {
    if (n == 1) return 0;
    return (ysf(n - 1, k) + k ) % n 
}

但是,回到本题,每一次拿的位置是递增的,这里的 k1=k2+1 ,只需稍作改变即可.

int ysf(int n, int k) {
    if (n == 1) return 0;
    return (ysf(n - 1, k + 1) + k ) % n 
}

AC_code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
typedef long long ull;
typedef long long ll;
typedef vector<int> vi;
#define xx first
#define yy second
#define rep(i, a, n) for (int i = a; i < n; i++)
#define sa(n) scanf("%d", &(n))
#define vep(c) for(decltype((c).begin()) it = (c).begin(); it != (c).end(); it++)
const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 12;

int fun(int n, int k) {
    if (n == 1) return 0;
    else return  (fun(n - 1, k + 1) + k) % n;
}

int main(void)
{
    int T;
    sa(T);
    while (T--) {
         int n;
         sa(n);
         printf("%d\n", fun(n, 1) + 1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值