Luogu6218 [USACO06NOV] Round Numbers S

https://www.luogu.com.cn/problem/P6218

数位\(DP\)

做一道简单题来复习一下数位\(DP\)

\[dp[ws][del][zero]\\ ws表示当前处理到哪一位\\ del表示0的个数与1的个数的差值\\ zero表示当前数字是否全为前导0(定义true表示不全为前导0,false表示是全为前导0)\\ 转移时套路地带上一个表示前几位是否与原数相同的flag\\ OK! \]

\(C++ Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define G 65
using namespace std;
int l,r,cnt,a[40],dp[40][105][2];
int dfs(int ws,int del,bool zero,bool flag)
{
    if (del+ws-32<0)
    {
        if (flag)
            dp[ws][del][zero]=0;
        return 0;
    }
    if (ws==0)
        return 1;
    if (flag&&~dp[ws][del][zero])
        return dp[ws][del][zero];
    int ans=0;
    int sh=(flag)?1:a[ws];
    for (int i=0;i<=sh;i++)
        ans+=dfs(ws-1,del+((zero || (i==1))?((!i)?1:-1):0),zero||(i==1),flag||(i!=a[ws]));
    if (flag)
        dp[ws][del][zero]=ans;
    return ans;
}
int S(int x)
{
    cnt=0;
    while (x)
    {
        a[++cnt]=x%2;
        x/=2;
    }
    return dfs(cnt,32,0,0);
}
int main()
{
    for (int i=0;i<=35;i++)
        for (int j=0;j<=G;j++)
            for (int k=0;k<2;k++)
                dp[i][j][k]=-1;
    scanf("%d%d",&l,&r);
    printf("%d\n",S(r)-S(l-1));
    return 0;
}
posted @ 2020-07-31 16:50  GK0328  阅读(66)  评论(0编辑  收藏  举报