9.6腾讯音乐笔试第二题可爱串 2(3)维dp

思路:先统计所有的含red子串的可能(可连续可不连续),然后统计含连续red的可能,前者减去后者。

前者设计4个状态,对应ABCD,分别是:A没出现r,B前面仅出现r,C,前面以此出现re。D依次出现red

A【i】【j】的含义:i取012代表分别red结尾,j代表序列长度-1,A表示这样的取值所处状态,注意有一些矩阵由于违反规定一直是0,可以不更新。

ABCD中有若干转移方程,注意特殊情况,可以从上级转移到下级,否则,只能同级转换。代码未取模。

#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
class Solution
{
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param n int整型
     * @return int整型
     */


    int kawaiiStrings(int n)
    {
        long long A[3][n];//前面无r
        long long B[3][n];//出现r        
        long long C[3][n];//出现re        
        long long D[3][n];//出现red        
        
        memset(A, 0, sizeof(A));
        memset(B, 0, sizeof(B));
        memset(C, 0, sizeof(C));
        memset(D, 0, sizeof(D));
        //cout << "OK";
        A[0][0]=0;
        A[1][0]=1;       //e
        A[2][0]=1;       //d
        
        B[0][0]=1;       //r
        
        B[2][1]=1;      //rd
        
        C[1][1]=1;      //re
        
        D[2][2]=1;      //red
        
        
        //C[2][2]=1;

        //cout << "OK";
        
        
        for (int i=1;i<n;i++){
            //A[0][i]=0;
            A[1][i]=A[1][i-1]+A[2][i-1];
            A[2][i]=A[2][i-1]+A[1][i-1];      
            
            B[0][i]=B[2][i-1]+B[0][i-1]+A[1][i-1]+A[2][i-1];
            //B[1][i]=0;
            B[2][i]=B[2][i-1]+B[0][i-1];
            
            C[0][i]=C[0][i-1]+C[1][i-1];
            C[1][i]=C[1][i-1]+C[0][i-1]+B[0][i-1]+B[2][i-1];
            //C[2][i]=0;
            
            D[0][i]=D[0][i-1]+D[1][i-1]+D[2][i-1];
            D[1][i]=D[1][i-1]+D[0][i-1]+D[2][i-1];
            D[2][i]=D[2][i-1]+C[1][i-1]+D[0][i-1]+D[1][i-1]+C[0][i-1];
      
        }
        
        long long ans = 0;
        for (int i = 0; i < 3; ++i)
            ans = (ans + D[i][n-1]) ;
        
        //没有连续red    
        long long no_red[n+1];
        memset(no_red, 0, sizeof(no_red));
        no_red[0]=1;
        no_red[1]=3;
        no_red[2]=9;
        for (int i=3;i<=n;i++)
            //没有连续red  
            no_red[i] = (no_red[i - 1] * 3 - no_red[i - 3]);
        //有连续red   
        //print(pow(3,n)-no_red[n])

            
        return ans-((pow(3,n)-no_red[n]));
    }
};
int main()
{
    Solution S;
    int n;
    cin>>n;
    cout << S.kawaiiStrings(n);
    return 0;
}

全部评论
大佬牛逼
点赞
送花
回复
分享
发布于 2023-09-11 10:43 浙江

相关推荐

1 2 评论
分享
牛客网
牛客企业服务