题目大意
给定 n 个人从左到右站成一排。每个人的身份只有两种:诚实者或欺诈者。
任务是统计:一共有多少种身份安排(每个人是诚实者或欺诈者)能够与所有人的发言同时不矛盾。结果对 998244353 取模输出。
输入为两行:
-
第一行是 n。
-
第二行是 n 个整数 ai。
输出为一行:满足条件的方案数(取模后)。
样例:
1 2 3 4 5 6
| 输入: 6 0 0 0 0 0 0
输出: 2
|
样例含义:6 个人都说自己左边有 0 个欺诈者。在“欺诈者不相邻”的前提下,能成立的身份安排共有 2 种。
思路讲解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| for(int i=1;i<=N;++i){ if(i==1){ if(A[i]==0){ dp[i][1]=1; dp[i][0]=1; }else{ dp[i][0]=1; } continue; } dp[i][0]=dp[i-1][1]; if(A[i]==A[i-1]){ dp[i][1]+=dp[i-1][1]; dp[i][1]%=mod; } if(A[i]==A[i-2]+1){ dp[i][1]+=dp[i-1][0]; dp[i][1]%=mod; } }
|

AC代码
AC
http://10.199.227.101/contest/1005/problem/L1-7/submission-detail/2146
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include <bits/stdc++.h> #define debug(x) cerr<<#x<<":["<<x<<"]\n"; #define SZ(x) ((ll)x.size()) #define all(x) x.begin(),x.end()
using namespace std; using ll = long long; using DB = double; const DB pi = acos(-1.0); const ll mod = 998244353; const ll INF = (1ll<<61)-1; ll lT;
void Solve(){ ll N; cin>>N; vector<ll> A(N+2); for(int i=1;i<=N;++i){ cin>>A[i]; } vector<array<ll,2>> dp(N+2); for(int i=1;i<=N;++i){ if(i==1){ if(A[i]==0){ dp[i][1]=1; dp[i][0]=1; }else{ dp[i][0]=1; } continue; } dp[i][0]=dp[i-1][1]; if(A[i]==A[i-1]){ dp[i][1]+=dp[i-1][1]; dp[i][1]%=mod; } if(A[i]==A[i-2]+1){ dp[i][1]+=dp[i-1][0]; dp[i][1]%=mod; }
} ll ans=dp[N][0]+dp[N][1]; ans%=mod; cout<<ans<<"\n";
} int main(){ cin.tie(0)->sync_with_stdio(false); Solve(); }
|
心路历程(WA,TLE,MLE……)