CF135E Weak Subsequence (计数问题)
题目大意:对于给定字符集大小k,求有多少个字符串满足它的最长【既是子串又是弱子序列】的长度为w;
神仙计数题
打表发现,对于字符串S而言,它的最长【既是子串又是弱子序列】,一定存在一个对应的子串,是S的前缀或者后缀
如果不是前缀或者后缀,那么它一定还可以向两边扩展
这启示我们分类讨论
容易发现,最优的情况一定是除了最后一位以外,其它每个字符都在相同的位置取,最后一位在其他位置取来构成弱子序列。
我们重点考虑最后一位带来的影响,
假设现在我们找到了一个字符串$w$作为子串,在后面接上一段字符串$L$
我们要保证$w$是最长的【既是子串又是弱子序列】才能正确地统计答案
1.$L$中一定存在一个字符和第$w$个字符相等
2.$L$中每个字符都不相等,否则继续向前取还能更长
3.前$L$个字符互不相等,否则从后面开始取能更长
有了这三个条件,我们就可以开始讨论了:
1.$w-L\geq 2$时,把序列分成5块,$[1,L], L+1, [L+2,w-1], w, [w+1,w+L]$
$[1,L]$存在一个字符和第L+1位相等,$[w+1,w+L]$位存在一个字符和第$w$位相等,两种情况取交集,可得答案为:
$k^{w-L-2}((A_{k}^{L})^{2}k^{2}-(A_{k}^{L+1})^{2})$
中间$w-L-2$个随便取,两边$L$个分别从$k$个里取且互不相等,第$L+1$个和第$w$个先假设随便取,再去掉两边都没有相同的情况
2.$w-L=1$时,把序列分成3块,$[1,L], w, [w+1,w+L]$
$[1,L]$位存在一个字符和第$w$位相等,$[w+1,w+L]$位存在一个字符和第$w$位相等,取交集,答案为:
$k(A_{k}^{L})^{2}-A_{k}^{L+1}A_{k-1}^{L}$
比上面的情况还要简单,不解释了
3.$w\leq L$时,把序列分成5块,$[1,w-1], w, [w+1,L], L+1, [L+2,L+w]$
这种情况就比较复杂了,但大体思路不变
首先,中间$[w+1,L]$一共$L-w$个,是从$k$个里随便取的且互不相同,贡献是$A_{k}^{L-w}$
左右两边$w$个都是从$k-(L-w)$里随便取,贡献是$A_{k-(L-w)}^{w}$
两边都没有的情况的贡献呢?
$w, [w+1,L], L+1$都互不相同,贡献是$A_{k}^{L-w+2}$。前后$w-1$个都和中间$[w,L+1]$个互不相同,贡献是$A_{k-(L-w+2)}^{w-1}$
总贡献就是$A_{k}^{L-w}(A_{k-(L-w)}^{w})^{2}-A_{k}^{L-w+2}(A_{k-(L-w+2)}^{w-1})^{2}$
$L$里每个元素互不相同,所以长度最大就是$k$,暴力枚举然后计算即可
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define ll long long 5 #define N1 1000010 6 using namespace std; 7 const ll p=1000000007; 8 9 ll mul[N1],_mul[N1],inv[N1]; 10 int m,K,n; 11 inline ll C(int x,int y) 12 { 13 if(y>x) return 0; 14 return mul[x]*_mul[y]%p*_mul[x-y]%p; 15 } 16 inline ll A(int x,int y) 17 { 18 if(y>x) return 0; 19 return mul[x]*_mul[x-y]%p; 20 } 21 ll qpow(ll x,ll y) 22 { 23 if(y<0) return 0; ll ans=1; 24 for(;y;x=x*x%p,y>>=1) if(y&1) ans=ans*x%p; 25 return ans; 26 } 27 28 int main() 29 { 30 scanf("%d%d%d",&m,&K,&n); 31 int i,j,L; 32 mul[0]=mul[1]=_mul[0]=_mul[1]=inv[0]=inv[1]=1; 33 for(i=2;i<=K;i++) mul[i]=mul[i-1]*i%p, inv[i]=1ll*(p-p/i)*inv[p%i]%p, _mul[i]=_mul[i-1]*inv[i]%p; 34 ll ans=0; 35 for(L=1;L<=K&&n+L<=m;L++) 36 { 37 if(n-L>=2) (ans+=qpow(K,n-L-2)*(1ll*K*K%p*A(K,L)%p*A(K,L)%p-A(K,L+1)*A(K,L+1)%p+p)%p)%=p; 38 else if(n-L==1) (ans+=(1ll*K*A(K,L)%p*A(K,L)%p-A(K,L+1)*A(K-1,L)%p+p)%p)%=p; 39 else (ans+=(1ll*A(K,L-n)*A(K-(L-n),n)%p*A(K-(L-n),n)%p-A(K,L-n+2)*A(K-(L-n+2),n-1)%p*A(K-(L-n+2),n-1)%p)%p)%=p; 40 } 41 printf("%lld\n",(ans%p+p)%p); 42 return 0; 43 }