Problem J
Bits
Input: Standard Input
Output: Standard Output
A 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);
}