例题1
题目大意:求区间内0的个数比1的个数多的数的个数。
题目链接:
https://vjudge.net/contest/448380#problem/A
思路:dp [ pos ] [ cnt ] , pos代表枚举到第 pos 位,cnt 代表截止到当前位0的个数比1少的个数。注意 lead 前导零,limit 代表数位的上界。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
typedef long long ll;
const ll maxx = 10005;
ll dp[40][70];
ll a[maxx];
//lead 前导零 limit 数位上界
ll dfs(int pos, int cnt, bool lead, bool limit)
{
if(pos == -1)return cnt>=32;
if(!limit && !lead &&dp[pos][cnt]!=-1)return dp[pos][cnt];
int up = limit?a[pos]:1; //根据 limit 判断枚举的上界 up
int ans = 0;
for(int i=0;i<=up;i++)
{
if(lead && i==0)ans+=dfs(pos-1,cnt,lead,limit && i==a[pos]);
else ans+=dfs(pos-1,cnt+(i==0?1:-1),lead && i==0 ,limit && i==a[pos]);
}
if(!limit && !lead) dp[pos][cnt] = ans;
return ans;
}
// 分解数位
ll solve(ll x)
{
int pos = 0;
while(x)
{
a[pos++] = x%2;
x/=2;
}
return dfs(pos-1,32,1,1);
}
int main()
{
memset(dp,-1,sizeof(dp));
ll l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",solve(r)-solve(l-1));
}