题目描述
要求在一个字符串中没有任何一个长度超过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
而第四第五种事实上是等价于第一第二种的,由此我们得出结论,在有限制条件的情况下,
那么我们只需要判断有没有限制字符,再直接计算即可,但是呢有一个坑,我们这里需要用到快速幂,且一开始就需要对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;
}