您的位置:首页 > 其它

Wannafly挑战赛5 D题题解 数学

2017-12-08 23:53 375 查看
时间限制:C/C++ 1秒,其他语言2秒
空间限制: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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: