一、题目描述:

  有 n 张卡片,正面和反面各有一个数字,一开始全部正面朝上。

  你可以选择翻转一些卡片(也可以不反转),求出使每两张相邻的卡片上的数字都不相同的方案数。1<=n<=200000,答案对 998244353 取模。


二、做题思路:

  设:x[i]表示第 i 张卡片正面的数;
    y[i]表示第 i 张卡片反面的数;
    dp[i][1]表示在反转第 i 张卡片的情况下,1~i 所有卡片的方案总数;
    dp[i][0]表示不反转第 i 张卡片的情况下,1~i 所有卡片的方案总数。
  容易得出以下结论:
    if (x[i]!=x[i-1]) dp[i][0]+=dp[i-1][0];
    if (x[i]!=y[i-1]) dp[i][0]+=dp[i-1][1];
    if (y[i]!=x[i-1]) dp[i][1]+=dp[i-1][0];
    if (y[i]!=y[i-1]) dp[i][1]+=dp[i-1][1];
  答案即是 dp[n][0]+dp[n][1] 。注意取模。时间复杂度 O(n) 。


三、完整代码:

 1 #include<iostream>
 2 #define N 200010
 3 #define mod 998244353
 4 using namespace std;
 5 int n,x[N],y[N],dp[N][2];
 6 int main()
 7 {
 8     cin>>n;
 9     dp[1][0]=dp[1][1]=1;
10     for(int i=1;i<=n;i++)
11     {
12         cin>>x[i]>>y[i];
13         if(x[i]!=x[i-1])    dp[i][0]+=dp[i-1][0];
14         if(x[i]!=y[i-1])    dp[i][0]+=dp[i-1][1];
15         if(y[i]!=x[i-1])    dp[i][1]+=dp[i-1][0];
16         if(y[i]!=y[i-1])    dp[i][1]+=dp[i-1][1];
17         dp[i][0]%=mod;dp[i][1]%=mod;
18     }
19     cout<<(dp[n][0]+dp[n][1])%mod<<'\n';
20     return 0;
21 }

四、写题心得:

  因为基本上是自己想出来的,而且是头一次想出来有一点难度的动态规划题,所以非常兴奋哦!!!加油!!!

posted on 2023-03-04 15:57  trh0630  阅读(59)  评论(0)    收藏  举报