2023“钉耙编程”中国大学生算法设计超级联赛(2)Card Game

文章描述了一个关于算法设计的竞赛题目,涉及将牌按照特定规则从一个牌堆移动到另一个牌堆的问题。通过递推公式,求解在给定条件下能完成任务的最大牌数k,并给出了O(Tlogn)时间复杂度的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2023“钉耙编程”中国大学生算法设计超级联赛(2)Card Game

题目大意

n n n个牌堆,第一个牌堆有 k k k张牌,从下到上的点数分别为 ( k , k − 1 , k − 2 , … , 2 , 1 ) (k,k-1,k-2,\dots,2,1) (k,k1,k2,,2,1)。其余牌堆都是空堆。

你可以将一个牌堆顶部的牌移到另一个牌堆的顶部。在任意时刻,每堆牌从底部到顶部都要满足值递减且连续。

你的任务是要将所有牌从第一个牌堆移到第二个牌堆。

在已知 n n n的情况下,求使得你可以完成任务的 k k k的最大值。

输出答案模 998244353 998244353 998244353后的值。

T T T组数据。

1 ≤ T ≤ 1 0 5 , 2 ≤ n ≤ 1 0 9 1\leq T\leq 10^5,2\leq n\leq 10^9 1T105,2n109


题解

因为牌堆要求值递减且连续,所以最大的一张牌一定是从牌堆 1 1 1直接移到牌堆 2 2 2。在移动这张牌之前,我们要将其他牌从牌堆 1 1 1移到空牌堆,在移动完最大的牌之后在用类似的方法移回。移出起点牌堆和移入终点牌堆的过程是对称的,所以我们可以将问题转化为:有一个空的终点牌堆和若干个有牌的牌堆,你要将所有的牌移到终点牌堆。

f i f_i fi表示有 i i i个牌堆时的答案,显然 f 2 = 1 f_2=1 f2=1。当 n > 2 n>2 n>2时,我们先移动含有点数最大的牌的牌堆,此时除了终点牌堆以外的牌堆的牌都有牌且牌的点数都小于这个牌堆的任意一张牌,所以这些牌堆不能使用,这一步可以移动 f 2 f_2 f2张牌。然后我们移动剩下的牌堆中含有点数最大的牌的牌堆,由于上一步的操作,我们得到了一个新牌堆,于是在一部我们可以移动 f 3 f_3 f3张牌。以此类推,可得 f n = ∑ i = 2 n − 1 f ( i ) f_n=\sum\limits_{i=2}^{n-1}f(i) fn=i=2n1f(i),由递推式可得 f n = 2 n − 1 f_n=2^n-1 fn=2n1,由此即可得到答案。

时间复杂度为 O ( T log ⁡ n ) O(T\log n) O(Tlogn)

code

#include<bits/stdc++.h>
using namespace std;
const long long mod=998244353;
int t;
long long n,ans;
long long mi(long long t,long long v){
	if(!v) return 1;
	long long re=mi(t,v/2);
	re=re*re%mod;
	if(v&1) re=re*t%mod;
	return re;
}
int main()
{
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		ans=(mi(2,n-1)-1+mod)%mod;
		printf("%lld\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值