Educational Codeforces Round 52: E. Side Transmutations(burnside引理)

版权声明:本文为博主原创文章,你们可以随便转载 https://blog.csdn.net/Jaihk662/article/details/83033670

 

E. Side Transmutations

题意:

给一个字符集A,考虑所有长度为n的字符串S,里面所有的字符都来自于字符集A,再给出m个参数b[1]~b[m],定义一种改变字符串S的操作为按顺序执行如下内容:

  1. 从b[]里选一个当k
  2. 把S的前k个字符和后k个字符分别倒置,然后交换位置

定义两个字符串等价,当且仅当一个字符串能经过若干次上述操作后变成另一个字符串

统计有多少个本质不同的字符串,答案模998244353

思路:

考虑进行5次上述操作的操作序列为{b[1], b[4], b[5], b[6], b[4]},可以手推发现它和操作序列{b[1], b[5], b[6]} 等价,也就是说操作序列中如果同一个bi出现两次,那么这两次操作可以抵消,除此之外还会发现操作与顺序无关

那么根据Bunside引理

可以得出|G| = 2^m,也就是b[]的所有不同集合都是一个置换

然后上面公式求就可以了,可以依次算出每个b[i]对不动点的个数的贡献,具体见代码

扫描二维码关注公众号,回复: 3691195 查看本文章
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 998244353
LL b[200005];
LL Pow(LL a, LL b)
{
	LL ans = 1;
	while(b)
	{
		if(b%2)
			ans = ans*a%mod;
		a = a*a%mod;
		b /= 2;
	}
	return ans;
}
int main(void)
{
	int k, i;
	LL n, m, ans;
	scanf("%lld%d%lld", &n, &k, &m);
	for(i=1;i<=k;i++)
		scanf("%lld", &b[i]);
	ans = 1;
	for(i=1;i<=k;i++)
		ans = ans*(Pow(m, b[i]-b[i-1])+Pow(m, 2*(b[i]-b[i-1])))%mod;
	ans = ans*Pow(m, n-b[k]*2)%mod;
	ans = ans*Pow(Pow(2, k), mod-2)%mod;
	printf("%lld\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/83033670