导航

CF666C 题解

题目大意

多组询问。每次询问给定一个串 \(s\) 和一个长度 \(L\)
问有多少个长度为 \(L\) 的只包含小写字母的串, 有至少一个子序列等于 \(s\). (询问 组数不超过 10^5 , 总串长不超过 10^5 )

解题思路

代码

#include<cstdio>
#include<cstring>
using namespace std;
int pow25[100010],fac[100010],inv[100010],f[450][100010],mp[100010],n,m,l,op,cnt;
char s[100010];const int mod=1e9+7;
void dp(int x){
	f[mp[x]][x]=1;
	for(int i=x+1;i<=100000;++i)
		f[mp[x]][i]=(26ll*f[mp[x]][i-1]%mod+1ll*pow25[i-x]*fac[i-1]%mod*inv[x-1]%mod*inv[i-x]%mod)%mod;
}
int main(){
	pow25[0]=fac[0]=inv[0]=fac[1]=inv[1]=1;pow25[1]=25;
	for(int i=2;i<=100000;++i){
		fac[i]=1ll*fac[i-1]*i%mod;
		pow25[i]=25ll*pow25[i-1]%mod;
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	}
	for(int i=2;i<=100000;++i)inv[i]=1ll*inv[i]*inv[i-1]%mod;
	scanf("%d%s",&n,s);
	l=strlen(s);mp[l]=++cnt;dp(l);
	while(n--){
		scanf("%d",&op);
		if(op&1){
			scanf("%s",s);l=strlen(s);
			if(!mp[l])mp[l]=++cnt,dp(l);
		}
		else{
			scanf("%d",&m);
			printf("%d\n",f[mp[l]][m]);
		}
	}
}

posted on 2021-11-06 20:37  CHK666  阅读(98)  评论(1编辑  收藏  举报