UVa11645 - Bits(递推+高精度)

本文介绍了一种高效算法,用于计算从0到n之间所有整数的二进制表示中连续出现的“11”序列总数,并采用高精度处理以避免整数溢出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

简介:
A(n)表示n的二进制中有多少个“11”出现
计算A(0)+A(1)+…+A(n)

分析:
一眼看出递推式:

A(n)=A(n/2)+(n/2和n都是奇数 ? 1:0)

这个式子算A(n)是很简单啦,但是求前缀和我就GG了

这道题实际和 UVA 11038 这题类似,枚举中间,然后处理两边的情况。
不过本题最大的答案会超过ll,要用高精度,不过借鉴大佬的方法,直接用两个数字来保存一个数字,这样能保存到2个ll的长度,就足够存放答案了

tip

说实话我不大懂这道题

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long

using namespace std;

const ll M=1e13;
ll n,p,q;

void add(ll x)
{
    q+=x;
    p+=q/M;
    q%=M;
}

void solve()
{
    p=q=0;
    ll a=n,b=1;
    while (n>1)
    {
        add((n>>2)*b);
        if ((n&3)==3)
           add((a&(b-1))+1);
        b<<=1;
        n>>=1;
    }
    if (p)
    {
        printf("%lld",p);
        printf("%013lld\n",q);
    }
    else
        printf("%lld\n",q);
}

int main()
{
    int cas=0;
    while (scanf("%lld",&n)!=EOF&&n>=0)
    {
        printf("Case %d: ",++cas);
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值