• P6218 [USACO06NOV] Round Numbers S(数位DP)


    题目描述

    如果一个正整数的二进制表示中,00 的数目不小于 11 的数目,那么它就被称为「圆数」。

    例如,99 的二进制表示为 10011001,其中有 22 个 00 与 22 个 11。因此,99 是一个「圆数」。

    请你计算,区间 [l,r][l,r] 中有多少个「圆数」。

    输入格式

    一行,两个整数 l,rl,r

    输出格式

    一行,一个整数,表示区间 [l,r][l,r] 中「圆数」的个数。

    //求L到R之间圆数的个数
    //圆数:0的数目不少于1的数目
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    ll f[100][100][100];//f(i,j)表示搜到第i位,一共有j个0,k个1的合法方案数 
    int a[100],len;
    ll L,R;
    ll dfs (int pos,int st,int limit,int x,int y) {
    	//pos表示当前位置
    	//st表示前面是否全为0
    	//limit表示是否有最高位限制 
    	//x表示0的数量(不包含前导0)
    	//y表示1的数量
    	
    	if (pos<=0) {
    		if (st||x>=y) return 1;
    		else return 0;
    	} 
    	if (!limit&&f[pos][x][y]!=-1) return f[pos][x][y];
    	ll ans=0;
    	ll k=limit?a[pos]:1;
    	for (int i=0;i<=k;i++) {
    		if (st&&i==0) {
    			ans+=dfs(pos-1,st,limit&&i==k,x,y);
    		}
    		else {
    			if (i==0)
    				ans+=dfs(pos-1,0,limit&&i==k,x+1,y);
    			else
    				ans+=dfs(pos-1,0,limit&&i==k,x,y+1);
    		}
    	} 
    	if (!limit&&!st) f[pos][x][y]=ans;
    	return ans;
    }
    ll solve (ll x) {
    	len=0;
    	while (x) {
    		a[++len]=x%2;
    		x/=2;
    	}
    	memset(f,-1,sizeof(f));
    	return dfs(len,1,1,0,0);
    }
    int main () {
    	cin>>L>>R;
    	cout<<solve(R)-solve(L-1);
    }
  • 相关阅读:
    市面上的系统.
    linux /dev 常见特殊设备介绍与应用[loop,null,zero,full,random]
    Linux command 系统快捷键
    Qtcreator中常用快捷键总结
    开始新的博客征途
    css选择器顺序的小技巧
    推荐20个很有帮助的web前端开发教程
    炙手可热的前端资源大集合
    一款纯css实现的垂直时间线效果
    15款极具创造性的艺术创意
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14590335.html
Copyright © 2020-2023  润新知