题目描述
11 から �N までの番号がついた �N 枚のカードが一列に並んでいて、各 � (1≤ � < �)i (1≤ i < N) に対してカード �i とカード �+1i+1 が隣り合っています。 カード �i の表には ��Ai が、裏には ��Bi が書かれており、最初全てのカードは表を向いています。
今から、�N 枚のカードのうち好きな枚数 (00 枚でも良い) を選んで裏返すことを考えます。 裏返すカードの選び方は 2�2N 通りありますが、そのうち以下の条件を満たすものの数を 998244353998244353 で割った余りを求めてください。
- 選んだカードを裏返した後、どの隣り合う 22 枚のカードについても、向いている面に書かれた数が相異なる。
输入格式
入力は以下の形式で標準入力から与えられる。
�N �1A1 �1B1 �2A2 �2B2 ⋮⋮ ��AN ��BN
输出格式
答えを整数として出力せよ。
题意翻译
- 有 �n 个卡片排成一排,编号为 1,2,...,�1,2,...,n。
- 第 �i 个卡片的正面是 ��ai,反面是 ��bi。
- 现在你可以将每个卡片翻到正面或反面,使相邻两个卡片上的数字互不相同。
- 求方案数对 998244353998244353 取模。
- 1≤�≤2×1051≤n≤2×105,1≤��,��≤1091≤ai,bi≤109
输入输出样例
输入 #1复制
3 1 2 4 2 3 4
输出 #1复制
4
输入 #2复制
4 1 5 2 6 3 7 4 8
输出 #2复制
16
输入 #3复制
8 877914575 602436426 861648772 623690081 476190629 262703497 971407775 628894325 822804784 450968417 161735902 822804784 161735902 822804784 822804784 161735902
输出 #3复制
48
说明/提示
制約
- 1≤ � ≤ 2× 1051≤ N ≤ 2× 105
- 1≤ ��,�� ≤ 1091≤ Ai,Bi ≤ 109
- 入力は全て整数
Sample Explanation 1
裏返すカードの番号の集合を �S とします。 例えば �={2,3}S={2,3} を選ぶと、向いている面に書かれた数はカード 11 から順に 1,2,41,2,4 となるため条件を満たします。 一方 �={3}S={3} を選ぶと、向いている面に書かれた数はカード 11 から順に 1,4,41,4,4 となり、カード 22 とカード 33 の数が一致するため条件を満たしません。 条件を満たす �S は {},{1},{2},{2,3}{},{1},{2},{2,3} の 44 通りです。
核心思路
用f[i][0]来表示第i张选了正面,只考虑1-i且第i张选了正面的可能性。f[i][1]则为选反面。
因为,这一个牌能不能选正面只与上一张牌(即i-1)有关,所以,当前状态可以有上一张牌推导而出。
易错点:判断要写全,有可能会出现答案为0的情况。
具体转移看代码吧。
AC代码
#include<bits/stdc++.h>
using namespace std;
int n;long long mod= 998244353;
long long a[201000],b[201000];
long long f[201000][2];
int main(){
cin>>n;
for(int i = 1;i <= n;i++){
cin>>a[i]>>b[i];
}
f[1][0] = f[1][1] = 1;
for(int i = 2;i <= n;i++){
if(a[i] != a[i-1]&&a[i] != b[i-1])f[i][0] = (f[i-1][0]+f[i-1][1])%mod;
else if(a[i] == a[i-1]&&a[i] != b[i-1])f[i][0] = f[i-1][1];
else if(a[i] != a[i-1]&&a[i] == b[i-1])f[i][0] = f[i-1][0];
if(b[i] != a[i-1]&&b[i] != b[i-1])f[i][1] = (f[i-1][0]+f[i-1][1])%mod;
else if(b[i] == a[i-1]&&b[i] != b[i-1])f[i][1] = f[i-1][1];
else if(b[i]!= a[i-1]&&b[i] == b[i-1])f[i][1] = f[i-1][0];
}
cout<<(long long)(f[n][0]+f[n][1])%mod;
return 0;
}