【AtCoder】ABC104 We Love ABC

题目

beta传送门

题目大意

对于一个字符串 T T ,规定它的ABC number是这样的一个三元组的个数:(i,j,k) 1i<j<k|T| 1 ≤ i < j < k ≤ | T | )使得 Ti= T i = A Tj= T j = B Tk= T k = C

现在给你一个只含有ABC Q Q ?的字符串S,你需要用ABC把这些?填满,显然一共有 3Q 3 Q 种填法。对于每种填法,求出此时字符串的ABC number,输出这些ABC number的和模 109+7 10 9 + 7

分析

数学大法好。

只有ABC的情况

如果给你一个只有ABC的字符串 S S ,怎么用O(n)的方法算出它的ABC number
(提示:从字符串中的B入手,组合计数。)


对于字符串中的B,显然它前面的所有A它后面的所有C能够随便配对,如果第 i i 个字符前面A[i]A,后面有 C[i] C [ i ] C。如果 S[i] S [ i ] B,则包含 S[i] S [ i ] 的三元组共有 A[i]×C[i] A [ i ] × C [ i ] 个。

例如:ABCACA,对于唯一的一个B来说,它前面有 1 1 A,后面有2C,则前面的一个A,加上当前的B,可以和右面任何一个C配对。所以ABC number的三元组有: (i,j,k)=(1,2,3) ( i , j , k ) = ( 1 , 2 , 3 ) (1,2,5) ( 1 , 2 , 5 ) ,共 1×2=2 1 × 2 = 2 个。

把每个B对应的三元组个数加起来就是答案了,即:

1i|S|Si=B(A[i]×C[i]) ∑ 1 ≤ i ≤ | S | S i = B ( A [ i ] × C [ i ] )

加上?后的情况

发现?可以变成B,而?变成AC时在其他情况下已经讨论了,不能重复计算。所以直接把?当成BB也当成B,一模一样的计算就行了。

代码

#include<cstdio>
#include<cstring>

#define MAXN 1000000
#define MOD 1000000007
char str[MAXN+5];
long long Pow[MAXN+5];
long long A[MAXN+5],C[MAXN+5],M[MAXN+5],N[MAXN+5];

int main(){
    Pow[0]=1;
    for(int i=1;i<=MAXN;i++)//初始化3的幂
        Pow[i]=Pow[i-1]*3%MOD;
    scanf("%s",str+1);
    int len=strlen(str+1);
    for(int i=1;i<=len;i++){
        A[i]=A[i-1]+(str[i]=='A');
        M[i]=M[i-1]+(str[i]=='?');
    }
    for(int i=len;i>=1;i--){
        C[i]=C[i+1]+(str[i]=='C');
        N[i]=N[i+1]+(str[i]=='?');
    }//计算前后缀和
    long long Ans=0;
    for(int i=1;i<=len;i++){
        if(str[i]=='B'||str[i]=='?'){//问号当成B
            Ans=(Ans+
                 A[i]*C[i]*Pow[M[i-1]%MOD+N[i+1]]%MOD+
                 A[i]*N[i+1]%MOD*Pow[M[i-1]+N[i+1]-1]%MOD+
                 C[i]*M[i-1]%MOD*Pow[M[i-1]+N[i+1]-1]%MOD+
                 Pow[M[i-1]+N[i+1]-2]*M[i-1]%MOD*N[i+1])%MOD;
                 //几种情况
        }
    }
    printf("%lld",Ans);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值