• CF135E Weak Subsequence (计数问题)


    题目传送门

    题目大意:对于给定字符集大小k,求有多少个字符串满足它的最长【既是子串又是弱子序列】的长度为w;

    神仙计数题

    打表发现,对于字符串S而言,它的最长【既是子串又是弱子序列】,一定存在一个对应的子串,是S的前缀或者后缀

    如果不是前缀或者后缀,那么它一定还可以向两边扩展

    这启示我们分类讨论

    容易发现,最优的情况一定是除了最后一位以外,其它每个字符都在相同的位置取,最后一位在其他位置取来构成弱子序列。

    我们重点考虑最后一位带来的影响,

    假设现在我们找到了一个字符串$w$作为子串,在后面接上一段字符串$L$

    我们要保证$w$是最长的【既是子串又是弱子序列】才能正确地统计答案

    1.$L$中一定存在一个字符和第$w$个字符相等

    2.$L$中每个字符都不相等,否则继续向前取还能更长

    3.前$L$个字符互不相等,否则从后面开始取能更长

    有了这三个条件,我们就可以开始讨论了:

    1.$w-Lgeq 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.$wleq 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
    ",(ans%p+p)%p);
    42     return 0;
    43 }
  • 相关阅读:
    Python字符编码详解
    Python 编程规范
    希尔排序
    浅析 Python 的 metaclass
    c#通过数据集生成浏览页面
    QQ搜索群参数详解
    扩展名为HTM或HTML的文件图标不能正常显示的解决方案
    利用QQ2009协议,将抓包直接解密出ClientKey(SessionKey)
    用Sql语句还原,分离,删除数据库连接
    asp.net 导出excel 问题 (服务器的部署)
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10466041.html
Copyright © 2020-2023  润新知