洛谷P9554 「CROI · R1」浣熊的溪石 题解

6 篇文章 0 订阅
2 篇文章 0 订阅

原题:洛谷P9554 「CROI · R1浣熊的溪石

思路

  1. n = 1 n=1 n=1 时有 m + 2 m+2 m+2 种取值,直接输出答案 m + 2 m+2 m+2 即可,虽然不知道题目搞这个分类有啥用
  2. n > 1 n>1 n>1 时,需要考虑题中要求:两个互为相反顺序的序列记为相同,开始容易想到将全部随意排列的总情况数直接除以 2 2 2,但是这样对本身是回文的序列进行了错误的计数,因为回文的序列反过来为本身,并不会使情况数减少,所以答案为非回文序列的情况数除以 2 2 2 加上回文序列的情况数。

先算出回文序列的情况数(直接对序列的一半计数,另一半可以直接对应): ( m + 1 ) × m ⌈ n 2 ⌉ − 1 (m+1) \times m^{ \lceil \frac{n}{2}\rceil -1} (m+1)×m2n1

  • 为什么 n 2 \frac{n}{2} 2n 要向上取整?如果序列长度为奇数,则中间的位置的情况也要计数,序列长度为偶数,则直接计算一半即可。

而直接使用乘法原理,把每一位的情况数相乘,得出全部随意排列的总情况数 ( m + 1 ) ( m + 1 ) × m n − 2 (m+1)(m+1) \times m^{n-2} (m+1)(m+1)×mn2

所以直接根据上面的分析表示出答案为 ( m + 1 ) ( m + 1 ) × m n − 2 − ( m + 1 ) × m ⌈ n 2 ⌉ − 1 2 + ( m + 1 ) × m ⌈ n 2 ⌉ − 1 \frac{(m+1)(m+1) \times m^{n-2}-(m+1) \times m^{ \lceil \frac{n}{2}\rceil -1}}{2}+(m+1) \times m^{ \lceil \frac{n}{2}\rceil -1} 2(m+1)(m+1)×mn2(m+1)×m2n1+(m+1)×m2n1

注意本题需要取模,而式子出现了除法,需要先通过费马小定理(模数是质数故可以使用)计算 2 2 2 在模 998244353 998244353 998244353 意义下的逆元。

使用快速幂计算,总复杂度为 O ( T log ⁡ n ) O(T \log n) O(Tlogn)

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#define ull unsigned long long//注意数据范围 
using namespace std;
const ull Mod=998244353;
ull n,m,t;
ull qpow(ull a,ull p)//快速幂 
{
	ull ans=1;
	while(p)
	{
		if(p&1) ans=ans*a%Mod;
		a=a*a%Mod;
		p>>=1;
	}
	return ans;
}
const ull inv=qpow(2,Mod-2)%Mod;//2在模998244353意义下的逆元
int main()
{
	scanf("%llu",&t);
	while(t--)
	{
		scanf("%llu%llu",&n,&m);
		ull res;
		if(n==1) res=m+2;//特判 
		else res=(((m+1)%Mod*(m+1)%Mod*qpow(m,n-2)%Mod+Mod-(m+1)%Mod*qpow(m,(n+1)/2-1)%Mod)*inv%Mod+(m+1)%Mod*qpow(m,(n+1)/2-1)%Mod)%Mod;
		printf("%llu\n",res);
	}
	return 0;
}
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值