P4925 [1007] Scarlet的字符串不可能这么可爱

题目传送门

题目描述

要求在一个字符串中没有任何一个长度超过1的回文连续子串,且给定了字符集、长度。

字符集:一个字符串中不同字符的数量。例如,字符集是3的话,你可以认为字符串仅由“A”、“B”、“C”三个字母组成。

题目思路

直接步入最优解吧。

其实特别简单,相信排列组合大家都学过吧(小奥内容)。

先假设长度为5,字符集为4(除了回文外,无限制):

        第一位:没有字符被选,4种。

        第二位:不能选第一位的字符,3种。

        第三位:不能选第一位,第二位的字符(不然就有回文了),2种。

        第四位:不能选前两位的字符,第一位的也可以选,因为前两位不相同不会构成回文,2种。

        第五位:与第四位一样,只有前两位不能选,2种。

所以总共是不是有4∗3∗2∗2∗2=96种方法。

是不是发现每一个字符只是对前后两位有限制?

比如上方原本的例子,原来是4∗3∗2∗2∗2,我们可以先假设它限制的是1~5中的一位,再进行计算,结果如下

        第一位:X∗3∗2∗2∗2

        第二位:3∗X∗2∗2∗2

        第三位:3∗2∗X∗2∗2

而第四第五种事实上是等价于第一第二种的,由此我们得出结论,在有限制条件的情况下,ans=(k-1)*(k-2)^{l-2}

那么我们只需要判断有没有限制字符,再直接计算即可,但是呢有一个坑,我们这里需要用到快速幂,且一开始就需要对k取余,否则就会(亲身经历......)。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll mod;
ll x_pow(ll a,ll b) //快速幂
{
    ll sum=1;
    a%=mod;
    while(b!=0)
	{
        if(b&1!=0) 
        {
        	sum=sum*a%mod;
		}
        b=b>>1;
        a=a*a%mod;
	}
    return sum;
} 
int main()
{
	ll k,l,s,w;
	cin>>k>>l>>mod>>s>>w;
	k%=mod;
	ll ans=1;
	if(l==1)
	{
		if(s!=0)
		{
			cout<<1;
		}
		else
		{
			cout<<k;
		}
		return 0;	
	}
	if(s!=0) 
	{
		ans=ans*(k-1)%mod;	
	}
	else 
	{
		ans=ans*k*(k-1)%mod;
	}
	k-=2;
	ans=(ans*x_pow(k,l-2))%mod;
	cout<<ans;
	return 0;
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值