[BZOJ 1794] Linear Garden
Link:
Solution:
IOI2008官方题解:传送门
要求序号,其实就是算字典序比其小的序列个数
从而使用数位$dp$的思想来解题,关键在于维护序列要$balance$这个条件
可以将$P$看作$-1$,而将$L$看作$+1$,最终要保证整个序列在一个宽最多为2的横条内
接下来就可以用状压$dp$计算方案数了
但实际上由于只有两种状态,每一种情形下是能直接推出结论的:
1、如果在宽仅为1的横条内,贡献为$2^{floor(k)}+2^{ceil(k)-1}$
2、如果在宽为2的横条内,贡献为$2^{floor(t)}$
官方题解好像情况2的结论有错?
状压$dp$的神仙做法:传送门 ,有点没看懂正确性在哪里……
Code:
#include <bits/stdc++.h> using namespace std; const int MAXN=1e6+10; char s[MAXN]; int n,m,mx,mn,cur,l,pre[MAXN],res; int main() { scanf("%d%d%s",&n,&m,s);l=strlen(s); pre[0]=1;for(int i=1;i<=1e6;i++) pre[i]=pre[i-1]*2%m; for(int i=0;i<l;i++) { if(s[i]=='P') { if(max(mx,cur+1)-mn<=2) { float t=(l-i-(float)1)/2; if(max(mx,cur+1)-mn==1) (res+=pre[(int)floor(t)]+pre[(int)ceil(t)]-1+m)%=m; else (res+=pre[(int)floor(t)])%=m; } cur--;mn=min(mn,cur); } else cur++,mx=max(mx,cur); } printf("%d",(res+1)%m); return 0; }
Review:
1、对于按字典序排列的计数问题,都可以引申为数位$dp$的题目
2、每一位状态数较小时尝试推结论
注意数形结合