数位DP
传送
思路
简单的数位DP,假定每一位的字符前面是最大的字符,对于每一位的字符,小于当前字符的数量是(s[i]-'a'),此时如果这样选择,那么后面的每一个到字符串中间的字符都可以任选m个,设第i个到中间字符的数量是y,所以此时可以构成的满足条件的字符是\((s[i]-'a')*m^y\)
但是我们忽略了一种情况,如果全选最大的字符,会不会超出字典序,这种情况需要特判
举个例子理解
bcaaa
b可以选择 a , b
/ / \ \
\(m^y\) a b c
/ \ / \
\(2*(m^y-1)\)
以此类推
CODE
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10,mod=1e9+7;
#define ll long long
int n,m;
ll p[maxn];
int t;
int id=0;
int main(){cin>>t;while(t--){cin>>n>>m; string s;cin>>s;p[0]=1;for(int i=1;i<=n;++i) p[i]=((ll)p[i-1]%mod*m%mod)%mod;//预处理m的次方ll res=0;int mid=(n+1)/2;for(int i=0;i<mid;++i){res=(res%mod+(ll)(s[i]-'a')*(p[mid-i-1])%mod)%mod;//对于每一位一定满足条件的方案数res%=mod;}int t=0;//判断由最后一位构成的字符串是否满足条件(字典序小于给定的字符串)for(int i=mid-1,j=n-i-1;i>=0;++j,--i){if(s[i]!=s[j]){if(s[i]<s[j]){t=1;}}break;}res=(res+t)%mod;cout<<"Case #"<<++id<<": "<<res<<endl;}return 0;}