YBT高效进阶 5.3.2 区间圆数

YBT高效进阶 5.3.2 区间圆数

思路

预处理 不考虑前导0
设f[i][j]表示i位中j个0
f[i][j]=f[i-1][j-1]+f[i-1][j]
f[i][0]=1
特殊处理前导0
用数位DP

CODE

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int f[51][51];
bool s[51];
int digitDP(int x)
{
    
    
	if(!x)return 0;
	int i,j,s0=0,s1=0,tot=0,ans=0;
	for(i=1;i<32&&x;++i)s[++tot]=x&1,x>>=1;
	for(i=tot;i;--i)
	{
    
    
		if(s[i]&&i!=tot)for(j=0;j<i;j++)if(j+s0+1>=tot-j-s0-1)ans+=f[i-1][j];
		if(i!=tot)for(j=0;j<i;j++)if(j>=i-j)ans+=f[i-1][j];
		s0+=!s[i],s1+=s[i];
	}
	if(s0>=s1)++ans;
	return ans;
}
int main()
{
    
    
	int i,j,l,r;
	scanf("%d%d",&l,&r);
	for(f[0][0]=1,i=1;i<32;++i)
		for(f[i][0]=1,j=1;j<=i;++j)
			f[i][j]=f[i-1][j-1]+f[i-1][j];
	printf("%d",digitDP(r)-digitDP(l-1));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/117854642
今日推荐