题目 :
小C的二进制难题
描述
小 C 研究数学日渐憔悴,他最近对二进制数中 1 的个数十分感兴趣,他定义:cnt(x) 表示 x 的二进制下 1 的个数。
他想知道
∑
i
=
0
2
n
c
n
t
(
i
)
\sum_{i=0}^{2^n} cnt(i)
∑i=02ncnt(i) 的值 ,你能帮帮他吗? 由于值可能非常大你需要对答案模上 20190414。
Input
第一行包含一个整数
T(1≤T≤1000) 代表测试组数,对于每一组测试:
第一行一个整数
n (0≤n≤
1
0
6
10^6
106) ,n 的含义如上所述。
Output
对于每组测试,输出一行,表示答案。
Sample Input
2
2
100
Sample Output
5
13308891
思路
00000 0
00001 1
00010 2
00011 3
00100 4
00101 5
00110 6
00111 7
01000 8
01001 9
01010 10
01011 11
01100 12
01101 13
01110 14
01111 15
010000 16
观察规律可知
∑
i
=
0
2
n
c
n
t
(
i
)
\sum_{i=0}^{2^n} cnt(i)
∑i=02ncnt(i)=n*(2^n-1)+1。
比如n=2的时候,看上图,2的二进制和3的二进制开始有1的位数的时候(从第n位也就是第二位开始有1,所以有n列),后面是0的位数,正好是1的二进制1的位数(补全后行的个数正好是2^n-1 )再加上4的二进制1的个数,2^n的二进制的1的个数都为1个,所以可以推出上述公式。
代码
#include<iostream>
using namespace std;
long long a[1000006];
const long long Mod=20190414;
long long qmi(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%Mod;
b>>=1;
a=a*a%Mod;
}
return ans;
}
int main()
{
int t,n;
cin>>t;
a[0]=1;
for(long long i=1;i<=1000000;i++)
{
a[i]=(i*qmi(2,i-1)%Mod+1)%Mod;//这里用快速幂求2^n-1
}
while(t--)
{
cin>>n;
cout<<a[n]<<endl;
}
return 0;
}
注意事项
这里需要用一个数组存结果,防止重复计算,如果不用数组存的话会超时。计算的时候我也是用的快速幂计算的。
题目地址:小C的二进制难题