[BZOJ 1794] Linear Garden

Link:

BZOJ 1794 传送门

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、每一位状态数较小时尝试推结论

注意数形结合

猜你喜欢

转载自www.cnblogs.com/newera/p/9247725.html