【题解】51nod1074:约瑟夫环V2

原题传送门
具体数学上看的一愣一愣的,自己瞎想了想好像明白了
假设现在有 n n n个人,先是淘汰第 k k k个人,剩下 ( n − 1 ) (n-1) (n1)个人是这样排列的: k + 1 , k + 2 , . . . , n , 1 , 2 , . . . , k − 2 , k − 1 k+1,k+2,...,n,1,2,...,k-2,k-1 k+1,k+2,...,n,1,2,...,k2,k1
若是我们知道 ( n − 1 ) (n-1) (n1)个人中幸存者是 x x x,那么一一映射, n n n个人的幸存者就是 ( x + k ) (x+k) (x+k)% n n n
得到递推关系 a n s i = ( a n s i − 1 + k ) ans_i=(ans_{i-1}+k) ansi=(ansi1+k)% i i i,然后最终+1
但是时间复杂度为 O ( n ) O(n) O(n),不行
想到一次可以加一大堆k上去再取模,但不能加的太大导致答案出错,所以得到每次加的k的系数是 i − a n s k + 1 \frac{i-ans}{k}+1 kians+1
这样一堆一堆的加就没问题了
Code:

#include <bits/stdc++.h>
#define LL long long
using namespace std;

int main(){
	LL n, k, ans = 0;
	scanf("%lld%lld", &n, &k);
	for (LL i = 1; i <= n; ){
		LL x = (i - ans) / k + 1;
		if (i + x > n) x = n - i;
		if (!x) break;
		i += x;
		ans = (ans + x * k) % i;
	}
	printf("%lld\n", ans + 1);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值