HDU 4588 Count The Carries (数学,计数)

题意:给定两个十进制数,求二进制中,从x加到y的二进制进了多少位。

析:把这些数字的二进制纵向罗列出来,然后一位一位的把和加起来,最终得到总的进位数。从1到x,第i位上1的总数是x左移i+1位再右移i位后得到的,

(在第 0位上,1和0以1010101010的周期出现,并且每个周期一个1,在第1位上,1和0以11001100的周期出现,并且每个周期2个1,以此类推,
则第n位上的1的个数是x/2^n*2^(n-1),即先左移n+1位,再右移n位),如果x在i位上面上是1,特殊判断一下,求一下周期以外的1的个数,这个时候的1的个数是

a%(1<<k)+1。

如何求每一位上1的总数?0到8的二进制数如下:
8 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0 0     (0)
0 0 0 0 0 0 0 0 1   (1)
0 0 0 0 0 0 0 1 0   (2)
0 0 0 0 0 0 0 1 1   (3)
0 0 0 0 0 0 1 0 0   (4)
0 0 0 0 0 0 1 0 1   (5)
0 0 0 0 0 0 1 1 0   (6)
0 0 0 0 0 0 1 1 1   (7)
0 0 0 0 0 1 0 0 0   (8)
第一位是10交替出现,第二位是0011交替出现,第三位是00001111交替出现......
那么规律就出来了。代码如下:

#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
using namespace std ;
typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f3f;
const int maxn = 10000 + 5;

LL solve(LL num, int i){
    if(-1 == num)  return 0;

    LL ans = (num>>i+1)<<i;
    if(num & (1LL<<i))  ans += (num % (1LL<<i)) + 1LL;

    return ans;
}

int main(){
    int a, b;
    while(scanf("%d %d", &a, &b) == 2){

        LL ans = 0;
        LL sum = 0;
        for(int i = 0; i < 63; ++i){
            sum += solve(b, i) - solve(a-1, i);
            sum /= 2;
            ans += sum;
        }

        cout << ans << endl;
    }
    return 0;
}
时间: 2024-11-09 04:41:21

HDU 4588 Count The Carries (数学,计数)的相关文章

HDU 4588 Count The Carries(数学 二进制 找规律啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4588 Problem Description One day, Implus gets interested in binary addition and binary carry. He will transfer all decimal digits to binary digits to make the addition. Not as clever as Gauss, to make th

HDU 4588 Count The Carries(找规律,模拟)

题目 大意: 求二进制的a加到b的进位数. 思路: 列出前几个2进制,找规律模拟. #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <stack> #include <vector> using namespace std; int main() { int

HDU 4588 Count The Carries 数位DP || 打表找规律

2013年南京邀请赛的铜牌题...做的很是伤心,另外有两个不太好想到的地方....a 可以等于零,另外a到b的累加和比较大,大约在2^70左右. 首先说一下解题思路. 首先统计出每一位的1的个数,然后统一进位. 设最低位为1,次低位为2,依次类推,ans[]表示这一位上有多少个1,那么有 sum += ans[i]/2,ans[i+1] += ans[i]/2; sum即为答案. 好了,现在问题转化成怎么求ans[]了. 打表查规律比较神奇,上图不说话. 打表的代码 #include <algo

HDU 4588 Count The Carries (2013年南京邀请赛)

题目地址:HDU 4588 这题是学长跟我说的一道数位DP..然后我就按着数位DP去做的,倒是写出来了,但是一直TLE..后来用类似找规律的方法解出来了.. 首先这题其实就是求每位上总共有多少个1,然后不断从低位开始向高位进位. 方法是比如二进制为1010010的这个数,就可以拆成1000000+10000+10三个数,然后从0到111111就是0和1的一个全排序,那么每一位上的1的个数总和一定是占一半,然后首位+1,那么10000也可以这样算,然后累加起来就好了.但是还要注意的是,首位的1不只

Hdu 4588 Count The Carries (规律)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4588 思路: 0     0000 1     0001 2     0010 3     0011 4     0100 5     0101 6     0110 7     0111 8    1000 9    1001 10  1010 观察可知,第i位有(1<<i)个0,与(1<<i)个1,按照长度为(1<<(i+1))长度循环.则对于数n,可以求出1到n中各位

hdu 1812 Count the Tetris polya计数

哈哈哈,简单polya,公式自己推导. 不过这题需要用到大数,很久没写Java,调了好久. import java.math.*; import java.util.*; import java.io.*; public class Main{ public static void main(String args[]){ Scanner cin=new Scanner(System.in); int n; BigInteger c; while(cin.hasNextInt()) { BigI

hdu 1705 Count the grid(皮克定理)

题目链接:hdu 1705 Count the grid 题意: 给定一个三角形三点坐标,问三角形内有多少个坐标均为整数的点. 题解: 给定顶点坐标均是整点(或正方形格点)的简单多边形,皮克定理说明了其面积 S 和内部格点数目 n.边上格点数目 s 的关系:S = n +s/2+1 三角形两向量叉积/2=面积. 向量上整数点数为gcd(v.x,v.y)(此公式对于一条边上的结果不准确,但是三条边加在一起的和是准确的) 1 #include<bits/stdc++.h> 2 #define F(

HDU 4405 飞行棋上的数学期望

突然发现每次出现有关数学期望的题目都不会做,就只能找些虽然水但自己还是做不出的算数学期望的水题练练手了 题目大意: 从起点0点开始到达点n,通过每次掷色子前进,可扔出1,2,3,4,5,6这6种情况,扔到几前进几,当然对应飞行通道可以通过x直达一点y,x<y,计算到达n点或超过n 点要扔色子的次数的数学期望 从某一点 i 扔完色子可到达 i+1,i+2,i+3,i+4,i+5,i+6这6个点,令dp[i]为到达末尾的数学期望 那么到达之后6个点的数学期望是一样的,那么dp[i]=dp[i+1]*

hdu 4869 Turn the pokers(数学)

题目链接:hdu 4869 Turn the pokers 题目大意:给定n和m,表示有n次翻牌的机会,m张牌,一开始所有的牌均背面朝上,每次翻牌可以选择xi张牌同时翻转.问说最后有多少种能. 解题思路:只要确定最后正面朝上的牌的个数即可.所以在读入xi的时候维护上下限即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long l