链接:https://ac.nowcoder.com/acm/problem/14599
来源:牛客网
题目描述
给定一个小写字母字符串T
求有多少长度为m的小写字母字符串S满足,T是S的一个子序列(不需要连续)
输入描述:
第一行一个字符串T 第二行一个正整数m
输出描述:
输出答案对109+7取模的值
示例1
输入
复制
a 2
输出
复制
51
说明
长度为2的里面有a的串有51种
备注:
1<=|T|,m<=105
题意很明显,就是方案总数该怎么算呢。例如a长度为2,则往右边放一个字母有26中方案,左边有25种(除了a)。
如果是ab长度为4,共有三种放发,左0又2 左1右1 左2右0
如果往右边放两个答案为26*26
前面一个后面一个:26*c(2,1)*25
如果左边放两个:都放a前面,都放ab中间或者一个放a前面一个放a后面,答案是3*25*25.其实就是把b放后面枚举a,a有三种位置就是c(3,1)
其实就是一个组合数而已,需要用到逆元打表。// 自己还是默默想了好久。
#include<bits/stdc++.h>
const int maxx=1e5+15;
#define ll long long
const ll mod=1e9+7;
using namespace std;
char a[maxx];
ll f[maxx];
ll ff[maxx];
ll niyuan(ll a, ll b)
{
ll ans=1;
while(b)
{
if(b&1)
ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
ll c(ll n,ll m)
{
if(m>n) swap(n,m);
return (((f[n]*ff[m])%mod)*ff[n-m]%mod)%mod;;
}
int main()
{
ll i,j,m,n,k,t;
a[0]=1;
f[1]=1;
for(i=2;i<maxx;i++)
{
f[i]=f[i-1]*i;
f[i]%=mod;
}
for(i=1;i<maxx;i++) ff[i]=niyuan(f[i],mod-2);
ff[0]=1;
//printf("%lld\n",c(1,0));
scanf("%s%lld",a,&m);
n=strlen(a);
ll x=m-n;
ll ans=0;
for (i=n;i<=m;i++) // 左边放n-1 右边放m-i
{
ans+=c(i-1,n-1)*niyuan(25,i-n)%mod*niyuan(26,m-i)%mod;
ans%=mod;
}
printf("%lld\n",ans);
return 0;
}