时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给定一个小写字母字符串T
求有多少长度为m的小写字母字符串S满足,T是S的一个子序列(不需要连续)
输入描述:
第一行一个字符串T 第二行一个正整数m
输出描述:
输出答案对109+7取模的值
示例1
输入
a 2
输出
51
说明
长度为2的里面有a的串有51种
备注:
1<=|T|,m<=105
思路:
想法比较敲妙,为了避免重复清空发生,例如 a_ _ b_ _ c_ _ _ _,需保证a,b之间的不能为b ;b,c之间的不能为c 依次类推
在m个里面选择n个位置,枚举最后一个位置, 最后一个位置之前的只需放25种,最后往后的需放26种
需要用逆元
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9+7;
ll f[100005];
ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%MOD;p=p*p%MOD;q>>=1;}return f%MOD;}
//模乘法的逆
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b)
{
d=a;x=1;y=0;
}
else
{
ex_gcd(b,a%b,d,y,x);
y-=(a/b)*x;
}
}
ll inverse(ll a,ll n)
{
ll d,x,y;
ex_gcd(a,n,d,x,y);
return d==1?(x+n)%n:-1;
}
string s;
ll n,m;
int main()
{
// freopen("data.txt","r",stdin);
ios::sync_with_stdio(false);
cin >> s;
cin >> m;
n = s.size();
if(m<n)
{
cout << 0<<endl;
return 0;
}
ll ans = 0;
f[0]=1;
ll tx;
for(int i=n;i<=m;i++)
{
if(i==n)
{
tx=1;
}
else
{
ll tm = n-1;
ll tn = i-2;
tx = f[i-n-1] *(tn+1) %MOD;
tx *= inverse(tn+1-tm,MOD);
tx%=MOD;
f[i-n]=tx;
}
ll x = i-n;
ll y = m-i;
tx*=qpow(25,x);
tx%=MOD;
tx*=qpow(26,y);
tx%=MOD;
ans += tx;
ans%=MOD;
}
cout << ans<<endl;
return 0;
}