题目链接:https://www.luogu.org/problemnew/show/P4925
一开始没想出来的一道题目,感觉思想很巧妙的,有很多值得借鉴的地方,所以整理了下来:
首先考虑没有限制合法字符串:
一个很显然的结论就是,对于一个回文字串,如果长度为奇数的话,则必定包含一个长度为3的回文串;若长度为偶数的话,则必定包含一个长度为2的回文串。也就是说对于l>=3且k>=3的情况,我们只需考虑对于每一个位置的字符,使它一定不和前两位字符相同即可。根据数学知识可知:一共有k*(k-1)*(k-2)^(l-2)这么多种方案。
那么如果有限制的话,也就是说已经用了一个字符了,则剩下的总共有(k-1)*(k-2)^(l-2)这么多种方案。
对于其它的情况,由于数据较小,可以打表考虑一下。
code:
#include<iostream>
using namespace std;
typedef long long ll;
ll k, l, s, w;
int p;
ll pow(ll x, ll y) {
ll ans=1, base=x;
while (y!=0) {
if (y&1) ans=(ans*base)%p;
base=(base*base)%p;
y>>=1;
}
return ans;
}
int work() {
if (s==0) {
if (l==1) return k;
if (l==2) return k*(k-1)%p;
if (l>=3) {
if (k>=3) return ((k*(k-1))%p*pow(k-2, l-2))%p;
else return 0;
}
}
else {
if (l==1) return 1;
if (l==2) return k-1;
if (l>=3) {
if (k>=3) return ((k-1)*pow(k-2, l-2))%p;
else return 0;
}
}
}
int main() {
cin >> k >> l >> p >> s >> w;
k%=p;
cout << work();
return 0;
}