Codeforces1426 F.Number of Subsequences(枚举,组合数学推式子)

    科技2022-07-12  115

    题意:

    给定一个只包含“abc?”的字符串,其中’?'可以替换为abc的任意一种。 问对于所有可能的串,子序列abc的总和是多少。 答案对1e9+7取模。

    数据范围:n<=2e5

    解法:

    三 元 组 统 计 的 套 路 : 枚 举 中 间 的 b , 统 计 两 端 的 a 和 c 计 算 贡 献 。 三元组统计的套路:枚举中间的b,统计两端的a和c计算贡献。 bac

    假 设 左 边 有 x 个 ′ a ′ , y 个 ′ ? ′ 。 假设左边有x个'a',y个'?'。 xay?

    假 设 i 个 变 成 a , 那 么 y − i 个 就 变 成 b / c , 方 案 数 为 C ( y , i ) ∗ 2 y − i 假设i个变成a,那么y-i个就变成b/c,方案数为C(y,i)*2^{y-i} iayib/cC(y,i)2yi

    加 上 固 定 的 x 个 , 那 么 可 能 的 a 的 个 数 总 为 : ∑ i = 0 y C ( y , i ) ∗ 2 y − i ∗ ( x + i ) 加上固定的x个,那么可能的a的个数总为:\sum_{i=0}^yC(y,i)*2^{y-i}*(x+i) x,a:i=0yC(y,i)2yi(x+i)

    将 式 子 拆 开 变 为 : 将式子拆开变为: :

    ∑ i = 0 y C ( y , i ) ∗ 2 y − i ∗ i + ∑ i = 0 y C ( y , i ) ∗ 2 y − i ∗ x \sum_{i=0}^yC(y,i)*2^{y-i}*i+\sum_{i=0}^yC(y,i)*2^{y-i}*x i=0yC(y,i)2yii+i=0yC(y,i)2yix

    = ∑ i = 0 y C ( y , i ) ∗ 2 y − i ∗ i + ( 1 + 2 ) y ∗ x =\sum_{i=0}^yC(y,i)*2^{y-i}*i+(1+2)^{y}*x =i=0yC(y,i)2yii+(1+2)yx

    = ∑ i = 0 y C ( y , i ) ∗ 2 y − i ∗ i + 3 y ∗ x =\sum_{i=0}^yC(y,i)*2^{y-i}*i+3^{y}*x =i=0yC(y,i)2yii+3yx

    因 为 C ( n , m ) = n ! m ! ∗ ( n − m ) ! , 因 此 式 子 变 为 因为C(n,m)=\frac {n!}{m!*(n-m)!},因此式子变为 C(n,m)=m!(nm)!n!,

    ∑ i = 0 y y ! i ! ∗ ( y − i ) ! ∗ 2 y − i ∗ i + 3 y ∗ x \sum_{i=0}^y \frac {y!}{i!*(y-i)!}*2^{y-i}*i+3^{y}*x i=0yi!(yi)!y!2yii+3yx

    = ∑ i = 0 y y ! ( i − 1 ) ! ∗ ( y − i ) ! ∗ 2 y − i + 3 y ∗ x =\sum_{i=0}^y \frac {y!}{(i-1)!*(y-i)!}*2^{y-i}+3^{y}*x =i=0y(i1)!(yi)!y!2yi+3yx

    = y ∗ ∑ i = 0 y ( y − 1 ) ! ( i − 1 ) ! ∗ ( y − i ) ! ∗ 2 y − i + 3 y ∗ x =y*\sum_{i=0}^y \frac {(y-1)!}{(i-1)!*(y-i)!}*2^{y-i}+3^{y}*x =yi=0y(i1)!(yi)!(y1)!2yi+3yx

    = y ∗ ∑ i = 0 y ( y − 1 ) ! ( i − 1 ) ! ∗ ( y − i ) ! ∗ 2 y − i + 3 y ∗ x =y*\sum_{i=0}^y \frac {(y-1)!}{(i-1)!*(y-i)!}*2^{y-i}+3^{y}*x =yi=0y(i1)!(yi)!(y1)!2yi+3yx

    = y ∗ ∑ i = 0 y C ( y − 1 , y − i ) ∗ 2 y − i + 3 y ∗ x =y*\sum_{i=0}^yC(y-1,y-i)*2^{y-i}+3^{y}*x =yi=0yC(y1,yi)2yi+3yx

    = y ∗ ∑ i = 0 y C ( y − 1 , y − i ) ∗ 2 y − i + 3 y ∗ x =y*\sum_{i=0}^yC(y-1,y-i)*2^{y-i}+3^{y}*x =yi=0yC(y1,yi)2yi+3yx

    左 边 当 i = 0 时 = 0 , 那 么 下 标 可 以 改 为 从 i = 1 开 始 左边当i=0时=0,那么下标可以改为从i=1开始 i=0=0,i=1

    = y ∗ ∑ i = 1 y C ( y − 1 , y − i ) ∗ 2 y − i + 3 y ∗ x =y*\sum_{i=1}^yC(y-1,y-i)*2^{y-i}+3^{y}*x =yi=1yC(y1,yi)2yi+3yx

    y − i 可 以 替 换 为 i , 因 为 是 对 称 的 y-i可以替换为i,因为是对称的 yii,

    = y ∗ ∑ i = 0 y − 1 C ( y − 1 , i ) ∗ 2 i + 3 y ∗ x =y*\sum_{i=0}^{y-1}C(y-1,i)*2^i+3^y*x =yi=0y1C(y1,i)2i+3yx

    = y ∗ ( 2 + 1 ) y − 1 + 3 y ∗ x =y*(2+1)^{y-1}+3^y*x =y(2+1)y1+3yx

    = 3 y − 1 ∗ y + 3 y ∗ x =3^{y-1}*y+3^y*x =3y1y+3yx

    预 处 理 p o w ( 3 ) 即 可 预处理pow(3)即可 pow(3)

    上 面 计 算 的 是 左 边 的 数 量 , 右 边 一 样 的 上面计算的是左边的数量,右边一样的 ,

    参 考 : h t t p s : / / w w w . l u o g u . c o m . c n / b l o g / Z i g Z a g K m p / C F 1426 F − s o l u t i o n 参考:https://www.luogu.com.cn/blog/ZigZagKmp/CF1426F-solution https://www.luogu.com.cn/blog/ZigZagKmp/CF1426Fsolution

    code:

    #include<bits/stdc++.h> using namespace std; #define int long long const int maxm=2e5+5; const int mod=1e9+7; char s[maxm]; int p3[maxm]; int lx[maxm],rx[maxm]; int ly[maxm],ry[maxm]; int n; void init(){ p3[0]=1; for(int i=1;i<maxm;i++)p3[i]=1ll*p3[i-1]*3%mod; } signed main(){ init(); cin>>n; scanf("%s",s+1); for(int i=1;i<=n;i++){ lx[i]=lx[i-1]; ly[i]=ly[i-1]; if(s[i]=='a')lx[i]++; else if(s[i]=='?')ly[i]++; } for(int i=n;i>=1;i--){ rx[i]=rx[i+1]; ry[i]=ry[i+1]; if(s[i]=='c')rx[i]++; else if(s[i]=='?')ry[i]++; } int ans=0; for(int i=1;i<=n;i++){ if(s[i]=='b'||s[i]=='?'){ int L=0; L+=p3[ly[i-1]]*lx[i-1]%mod; if(ly[i-1])L+=p3[ly[i-1]-1]*ly[i-1]%mod; int R=0; R+=p3[ry[i+1]]*rx[i+1]%mod; if(ry[i+1])R+=p3[ry[i+1]-1]*ry[i+1]%mod; ans=(ans+L*R)%mod; } } cout<<ans<<endl; return 0; }
    Processed: 0.011, SQL: 8