I - [登峰造极-2016]_QAQ字符串

  • I - [登峰造极-2016]_QAQ字符串
  • 我们考虑至少包含 QAQ 的子串比较难求,所以我们反过来考虑,求不包含 QAQ 子串的字符串。 那么这是一个常见的动态规划问题。 我们定义 dp[i][j]的含义长度为 i,并且结尾的状态为 j 的方案数。 定义状态 0 为不构成 QAQ 任何前缀的结尾,比如 “QAAA”、“bLue”、“UMR” 等。 定义状态 1 为以 Q 字符为结尾,比如 “QWQ”、“QvQ” 等。 定义状态 2 为以 “QA” 为结尾,比如 AQA”,“AQQA” 等。 状态 0 可由状态 0 或状态 ‘2’ 加上任意非 ‘Q’ 的字符转移而来,或由状态 1 加上任意非 ‘Q’ 且非 ‘A’ 的字 符转移而来。 状态 1 可由状态 0 或状态 1 加上 ‘Q’ 字符转移而来。 状态 2 仅有状态 1 加上 ‘A’ 转移而来。
  • 特别注意: ans=(qpow(26,n)-(dp[n][0]+dp[n][1]+dp[n][2])%md+md)%md;  防止出现负数
  • #include<bits/stdc++.h>
    using namespace std;
    #define maxn 100005
    #define md 1000000007
    #define ll long long
    ll dp[maxn][5],n,ans;
    ll qpow(ll a,ll b)
    {
        ll sum=1;
        while(b)
        {
            if(b%2)
                sum=(sum*a)%md;
            a=(a*a)%md;
            b/=2;
        }
        return sum%md;
    }
    int main()
    {
        dp[0][0]=1;
        dp[0][1]=dp[0][2]=0;
        for(int i=1; i<=maxn; i++)
        {
            dp[i][0]=(25*(dp[i-1][0]+dp[i-1][2])+24*dp[i-1][1])%md;
            dp[i][1]=(dp[i-1][0]+dp[i-1][1])%md;
            dp[i][2]=dp[i-1][1]%md;
        }
        while(~scanf("%lld",&n))
        {
            ans=(qpow(26,n)-(dp[n][0]+dp[n][1]+dp[n][2])%md+md)%md;
            printf("%lld\n",ans);
        }
        return 0;
    }
    

猜你喜欢

转载自blog.csdn.net/BePosit/article/details/83109489