POJ 3252 区间内一个数的二进制中0的数量要不能少于1的数量(数位DP)

题意:求区间内二进制中0的数量要不能少于1的数量

分析:很明显的是数位DP;

菜鸟me : 整体上是和数位dp模板差不多的 , 需要注意的是这里有前导零的影响 , 所以需要在dfs()里面增加zor 变量的限制条件 ,

那么我们的dp[i][j] 是表示第i 位置 , ,0的数量减去1的数量不少于 j 的方案数 , 那剩下的就简单了咯 ,哦还需要注意的是 这里的 j 会出现负数的情况 , 那也很好解决咯 ,偏移下就好拉 , 从32开始 ,也就是说32表示0

#include<stdio.h>
#include<string.h>
int dp[40][70];
int a[70];
int dfs(int pos , int sta , int limit , int zor)
{
    if(pos==-1)
    return sta>=32;
    if(!limit && !zor && dp[pos][sta]!=-1)
    return dp[pos][sta];
    int up=limit?a[pos]:1;
    int ans=0;
    for(int i=0 ; i<=up ; i++)
    {
        if(zor && i==0)
        ans+=dfs(pos-1,sta,limit&&i==a[pos],zor&&i==0);
        else
        {
            if(i==0)
            ans+=dfs(pos-1,sta+1,limit&&i==a[pos],zor&&i==0);
            else
            ans+=dfs(pos-1,sta-1,limit&&i==a[pos],zor&&i==0);
        }

    }
    if(!limit && !zor)
    dp[pos][sta]=ans;
    return ans;
}
int so(int x)
{
    int ans=0;
    while(x)
    {
        a[ans++]=x%2;
        x/=2;
    }
    return dfs(ans-1,32,1,1);
}
int main( )
{
    int l,r;
    memset(dp,-1,sizeof(dp));
    while(scanf("%d%d",&l,&r)!=EOF)
    {
        printf("%d\n",so(r)-so(l-1));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/shuaihui520/p/9919327.html

时间: 2024-08-03 19:32:57

POJ 3252 区间内一个数的二进制中0的数量要不能少于1的数量(数位DP)的相关文章

[ACM] POJ 3252 Round Numbers (一个区间内二进制中0的个数大于等于1的个数有多少个,组合)

Round Numbers Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8590   Accepted: 3003 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors',

说一说,求一个正整数的二进制中0的个数

昨天突然看到一个算法题:一个正整数a的二进制中0的个数: 话说这是个老题了,直观的算法就每次右移一位,直到0为止:代码就省略了: 仔细想想有更好的方案么? 就是这个题可以转换成一个正整数~a的二进制中1的个数: 求1的个数这个貌似就很熟悉了吧: int num = 0; b = ~a; while(b){ num++; b = b & (b-1); } 是不是容易了许多呢 另外像java和python这种没有unsigned的语言要自己去转 b = ~a & 0x0ffff

剑指offer——二进制中0的个数

题目链接:输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 解题思路: 数字-1做与操作 1 public class Solution { 2 public int NumberOf1(int n) { 3 4 int count=0; 5 6 while(n!=0) 7 { 8 count++; 9 n = n &(n-1); 10 } 11 return count; 12 13 } 14 } 原文地址:https://www.cnblogs.com/wangyufeiai

计算二进制中1的个数

问题:计算某个数的二进制中1的个数 思路:x = x & (x-1) 将 x 的二进制最右面的一个 1 变为 0,其余保持不变.反复操作,直到变为 0 为止,计算操作次数,即为 x 的二进制中 1 的个数. 证明:假设 x 的二进制末尾为 10...0 [末尾有 k 个 0,k = 0,1,2,...]. 则 x - 1 的二进制末尾 k+1 位为 01...1 [末尾有 k 个 1,k = 0,1,2,...],其他与 x 相同. 从而 x & (x-1) 的末尾 k+1 位为 00..

剑指Offer:二进制中1的个数

题目:输入一个整数,输出该数二进制表示中1的个数. // 二进制中1的个数 #include <stdio.h> int wrong_count_1_bits(int n) // 错误解法: 当n为负数时, n>>=1右移, 最高位补1, 陷入死循环 { int count = 0; while(n) { if( n & 1 ) ++count; n >>= 1; } return count; } int count_1_bits(int n) // 常规解法

转载-求一个数转换成为二进制中1的个数

转载自:求一个数转换为二进制中1的个数 // Count1--01.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using namespace std; int coutn1(int num) { int result = 0; while (num) { result+=num&0x01;//如果是1的话,整个个数加1,如果是0的话,那么就是+0:这样就可以知道二进制中1的个数了

Binary system(求区间内二进制中1的个数最多的数)

Description 给定一个范围[a,b]  (0<=a<b<=10^18) 求出该范围内二进制中1的个数最多的数,如果存在多个答案,输出最小的那个数 Input 输入数据有多组,每组数据输入两个整数a,b,表示区间[a, b]. Output 输出该区间内二进制的1最多的整数,如果有多个数二进制1的个数相同,输出最小的那个数. Sample Input 4 87 14 Sample Output 77 HINT 思路: 区间[a,b],如果a==b,输出a, 先把a,b化为二进制数

二进制中1的个数

题目描述: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 输入: 输入可能包含多个测试样例. 对于每个输入文件,第一行输入一个整数T,代表测试样例的数量.对于每个测试样例输入为一个整数. .n保证是int范围内的一个整数. 输出: 对应每个测试案例, 输出一个整数,代表输入的那个数中1的个数. 样例输入: 3 4 5 -1 样例输出: 1 2 32 /* 二进制中1的个数 by Rowandjj 2014/7/24 */ #include<stdio.h> #include

nyoj 数的二进制中1的个数

很有用O(n)内实现三类数字分离,以前大多是分成两类数据,快排中分成两类,还有就是"ab***vvvc" 在O(n)中变成 abvvc****,变成两类划分问题 #include<iostream> #include<string.h> using namespace std; const int N=1000; char c[N]; int len; void swap(char &a,char &b) { //a=a^b; //b=a^b;