Uva 11645 - Bits 解题报告(递推+大数)

96 篇文章 0 订阅

Problem J
Bits 
Input: 
Standard Input

Output: Standard Output

 

bit is a binary digit, taking a logical value of either "1" or "0" (also referred to as "true" or "false" respectively).  And every decimal number has a binary representation which is actually a series of bits. If a bit of a number is “1” and it's next bit is also “1” then we can say that the number has a 1 adjacent bit. And you have to find out how many times this scenario occurs for all numbers up to N.

 

Examples:

            Number           Binary                         Adjacent Bits

            12                    1100                            1

            15                    1111                            3

            27                    11011                          2

 

Input

For each test case, you are given an integer number (0 <= N <= ((2^63)-2)), as described in the statement. The last test case is followed by a negative integer in a line by itself, denoting the end of input file.

 

Output

For every test case, print a line of the form “Case X: Y”, where X is the serial of output (starting from 1) and Y is the cumulative summation of all adjacent bits from 0 to N.

 

Sample Input                             Output for Sample Input

0

6

15

20

21

22

-1

Case 1: 0

Case 2: 2

Case 3: 12

Case 4: 13

Case 5: 13

Case 6: 14



    解题报告; 自己想的,不过WA了几次在高精度上。

    对于一个数,我们先将其转化为二进制的形式。例如110110001。从高位向低位遍历。第一位是1,那么所有0********的串都符合条件,我们求出********的串中有多少11即可。对于这种串中有多少11,我们可以用概率的方式去求。第一位是1的概率是1/2,第二位是1的概率也是1/2,那么1,2位组成11的概率是1/4,总串数是2^8,那么********串中的11的数量为2^8*(1/4*7)。另外,如果遍历到当前数是1,上一位也是1,那么后面的数字都符合条件了(例如110000000到110110001),答案加上这样的数。

    简单写了个高精度,代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

typedef long long LL;
const int K = 10000;
const int M = 10;
const char show[] = "%04d";

struct Bignum
{
    LL a[M*2];
    Bignum()
    {
        memset(a, 0, sizeof(a));
    }

    Bignum(LL num)
    {
        memset(a, 0, sizeof(a));

        int t=0;
        while(num)
            a[t++]=num%K,num/=K;
    }

    Bignum operator+(const Bignum& b)
    {
        Bignum c;
        for(int i=0;i<M;i++)
            c.a[i]=a[i]+b.a[i];
        c.metain();
        return c;
    }

    Bignum operator+(LL num)
    {
        return *this+Bignum(num);
    }

    void metain()
    {
        for(int i=0;i<M;i++) if(a[i]>=K)
            a[i+1]+=a[i]/K,a[i]%=K;
    }

    Bignum operator*(const Bignum& b)
    {
        Bignum c;
        for(int i=0;i<M;i++) for(int j=0;j<M;j++)
            c.a[i+j] += a[i]*b.a[j];
        c.metain();
        return c;
    }

    void output()
    {
        int t=M*2;
        while(a[--t]==0 && t>0);
        printf("%lld", a[t--]);
        for(int i=t;i>=0;i--)
            printf(show, abs(a[i]));
        puts("");
    }
};

int dd[1000];
int dNum=0;

LL two[1000];
void init()
{
    two[0]=1;
    for(int i=1;i<=64;i++)
        two[i]=two[i-1]*2;
}

void decomposition(LL n)
{
    dNum=0;
    memset(dd, 0, sizeof(dd));

    while(n>0)
        dd[dNum++]=n%2,n>>=1;
}

int cas=1;
void work(LL n)
{
    decomposition(n);

    Bignum ans(0);
    for(int i=dNum-1;i>=0;i--)
    {
        if(dd[i]==1)
        {
            if(i>=2)
                ans=ans+Bignum(two[i-2])*(i-1);

            if(dd[i+1]==1)
                ans=ans+(n%two[i]+1);
        }
    }

    printf("Case %d: ", cas++);
    ans.output();
}

int main()
{
    init();

    LL n;
    ios::sync_with_stdio(false);
    while(cin>>n && n>=0)
        work(n);
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值