ABC 291 D - Flip Cards(状态机)
https://atcoder.jp/contests/abc291/tasks/abc291_d
题目大意:
n张卡片排成一行。每张卡片正面是数字ai,背面是数字bi。最初,所有的牌都处于正面状态。
随机翻转>=0张卡片。问这一列是否相邻中的数字都是不同的,是就可行,求出这样可行的方法数量(以998244353为模)。
Sample Input 1
Copy
3
1 2
4 2
3 4
Sample Output 1
Copy
4
(一开始没有看到是相邻卡片不可相等的状态,知道是状态机,但是想半天都没有想出方案,一看佬儿的写法,嗷~我看错题了原来又hh)
【注意取模】
写法一
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18,MINN=-1e18;
const LL N=2e5+10,M=4010;
const LL mod=998244353;
const double PI=3.1415926535;
#define endl '\n'
LL a[N][3],f[N][3];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
//cin>>T;
while(T--)
{
LL n;
cin>>n;
for(int i=1;i<=n;i++) //n张卡片,0表示正面状态,1表示反面状态
{
cin>>a[i][0]>>a[i][1];
}
f[1][0]=1; //第一张卡片的正面肯定算一种方案
f[1][1]=1; //第一张卡片的反面也肯定算一种方案
for(int i=2;i<=n;i++) //从第二张卡片开始
{
for(int j=0;j<=1;j++) //当前卡片的两种状态
{
for(int k=0;k<=1;k++) //前面一张卡片的两种状态
{
if(a[i][j]!=a[i-1][k]) //如果这张卡片的数字和前面一张的不一样
f[i][j]=(f[i][j]+f[i-1][k])%mod; //那么就可以把前面的数量加起来
}
}
}
cout<<(f[n][0]+f[n][1])%mod<<endl; //最后的答案就是两种状态的总数和
}
return 0;
}
写法二
意思和写法一 一致,就不赘述咯~
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18,MINN=-1e18;
const LL N=2e5+10,M=4010;
const LL mod=998244353;
const double PI=3.1415926535;
#define endl '\n'
LL a[N],b[N],f[N][3];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
//cin>>T;
while(T--)
{
LL n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
}
f[1][0]=1;
f[1][1]=1;
for(int i=2;i<=n;i++)
{
if(a[i]!=a[i-1]) f[i][0]=(f[i][0]+f[i-1][0])%mod;
if(a[i]!=b[i-1]) f[i][0]=(f[i][0]+f[i-1][1])%mod;
if(b[i]!=a[i-1]) f[i][1]=(f[i][1]+f[i-1][0])%mod;
if(b[i]!=b[i-1]) f[i][1]=(f[i][1]+f[i-1][1])%mod;
}
cout<<(f[n][0]+f[n][1])%mod<<endl;
}
return 0;
}