【JZOJ4812】string
Description
给出一个长度为n, 由小写英文字母组成的字符串S, 求在所有由小写英文字母组成且长度为n 且恰好有k 位与S 不同的字符串中,给定字符串T 按照字典序排在第几位。
由于答案可能很大,模10^9 + 7 输出。
Solution
转化题目,我们要求的就是字典序比T小且恰有k位和S不同的字符串个数。
我们假设当前做到第
i
位,前
如果
如果 Si≠Ti ,分两种情况,如果 Si<Ti ,那么分别计算相等和不等的情况,如果 Si>Ti ,则直接计算即可。
然后对于
Si≠Ti
,我们让
k
减去
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100010
#define mo 1000000007
#define ll long long
using namespace std;
char s[N],t[N];
int a[N],b[N];
ll mi[N],jc[N],ny[N];
ll pow(ll m,int n)
{
ll b=1;
while(n)
{
if(n%2) b=b*m%mo;
n/=2;
m=m*m%mo;
}
return b;
}
ll c(int m,int n)
{
return jc[m]*ny[m-n]%mo*ny[n]%mo;
}
int main()
{
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
int n,k;
cin>>n>>k;
scanf("%s",s+1);
scanf("%s",t+1);
jc[0]=mi[0]=ny[0]=1;
fo(i,1,n)
{
a[i]=s[i]-'a';
b[i]=t[i]-'a';
jc[i]=jc[i-1]*i%mo;
ny[i]=pow(jc[i],mo-2);
mi[i]=mi[i-1]*25%mo;
}
ll ans=1;
fo(i,1,n)
if(a[i]==b[i]) ans=(ans+b[i]*mi[k-1]%mo*c(n-i,k-1)%mo)%mo;
else
{
if(a[i]<b[i])
{
ans=(ans+(b[i]-1)*mi[k-1]%mo*c(n-i,k-1)%mo)%mo;
if(k<=n-i) ans=(ans+c(n-i,k)%mo*mi[k]%mo)%mo;
}
else ans=(ans+b[i]*mi[k-1]%mo*c(n-i,k-1)%mo)%mo;
k--;
}
cout<<ans;
}