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;
}