G - Gig Combinatorics
题意:给你由{1,2,3}组成的序列,问1为开头,3为结尾,中间全为2的子序列有多少个?答案取模。
思路:DP, dp[i][j] 定义为 到i为止以j结尾的个数,2需要稍微推一下,例如11212 这种序列,设当前i的位置为第二个2,可以看出,第二个前面的3个1都可以,即dp[i-1][1],但还要考虑2结尾,可以发现,前一个2的(1,2),(1,2)序列同样适用于后面的2,即第一个2前面的1与第二个2组成的子序列(1,2)(1,2),也可以(1,2,2)(1,2,2) 所以再加个dp[i-1][2]*2。
#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof(a))
#define up(i, a, b)for(int i = a;i <= b; i++)
#define down(i, a, b)for(int i =a;i >= b; i--)
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int maxn = 1e6 + 200;
const int mod = 1e9 + 7;
int dp[maxn][4];
signed main()
{
int n, x;
cin >> n;
up(i, 1, n){
cin >> x;
if(x == 1)dp[i][1] = (dp[i-1][1] + 1 )% mod;
else dp[i][1] = dp[i-1][1];
if(x == 2)dp[i][2] = (dp[i-1][1] + dp[i-1][2] + dp[i-1][2])%mod;
else dp[i][2] = dp[i-1][2];
if(x == 3)dp[i][3] = (dp[i-1][3] + dp[i-1][2])%mod;
else dp[i][3] = dp[i-1][3];
// cout << dp[i][1] <<' ' << dp[i][2] << ' ' << dp[i][3] << endl;
}
printf("%lld\n", dp[n][3]);
return 0;
}