P1030 鹧鸪天 官方题解
Gioush OJ · P1030 鹧鸪天
鹧鸪天
【题意简述】
设第 盏灯的状态为 ,并令边界外的 。给定
求共有多少个状态序列满足全部条件。
【Hint】
只需要枚举第一盏灯的状态,之后每个位置都会被上一条等式唯一推出。
【提示】
固定 并枚举 后,由 可以依次推出 。
【解法】
令 ,枚举 。对 ,递推
若某次推出的 不在 中,则该枚举无效。最后还需要检查右端边界:
两个初始状态至多产生两个候选方案,统计其中合法的方案数即可。
【边界检查】
固定 已经处理了左端边界;枚举 后,递推时每个 都被唯一确定,若不在 中立刻舍弃。最后检查 ,等价于验证右端边界 。
【复杂度】
只有两种初值。每次枚举线性递推,时间复杂度为 ,空间复杂度为 。
【参考代码】
/*Author:EhundateghDate:2026/7/23Name:skycall.cppYou steal,I kill.*/#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 200010using namespace std;int Line[MAXN],n,Ans=0;int Dp[MAXN];bool Tag=1;void Solve(){ Ans=0;Tag=1; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&Line[i]); } Dp[0]=0;Dp[1]=0; for(int i=2;i<=n;i++){ if(Line[i-1]-Dp[i-1]-Dp[i-2]>1||Line[i-1]-Dp[i-1]-Dp[i-2]<0) {Tag=0; break;} else if(Line[i-1]-Dp[i-1]-Dp[i-2]==1){ Dp[i]=1; } else if(Line[i-1]-Dp[i-1]-Dp[i-2]==0){ Dp[i]=0; } } if(Line[n]!=Dp[n-1]+Dp[n]) Tag=0; if(Tag) Ans++; Dp[0]=0;Dp[1]=1; Tag=1; for(int i=2;i<=n;i++){ if(Line[i-1]-Dp[i-1]-Dp[i-2]>1||Line[i-1]-Dp[i-1]-Dp[i-2]<0) {Tag=0; break;} else if(Line[i-1]-Dp[i-1]-Dp[i-2]==1){ Dp[i]=1; } else if(Line[i-1]-Dp[i-1]-Dp[i-2]==0){ Dp[i]=0; } } if(Line[n]!=Dp[n-1]+Dp[n]) Tag=0; if(Tag) Ans++; printf("%d\n",Ans); return;}int main(){ int c,T; freopen("skycall.in","r",stdin); freopen("skycall.out","w",stdout); scanf("%d%d",&c,&T); while(T-->0) Solve(); return 0;}