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;
}

