给定一个n,求1-n对应的二进制数中0出现的总次数
我是枚举了几个数之后推导出来的,并没有严谨性证明
因为没有看到输出要求的mod2007,还去贴了个大数模板...
后来看ppt上才知道要mod2007,然后再交自己的代码就A了
枚举n=0, 1, 2, 3, 4, 5后发现:
f(0) = 0
f(1) = 1
f(2) = 3
f(3) = 8
f(4) = 21
f(5) = 54
令f(n) = 2*f(n-1)+g(n)
g(2) = g(1)+2-1 = 2
g(3) = g(2)+2^2-1 = 5
g(4) = g(3)+2^3-1 = 12
可以发现g(n)-g(n-1) = 2^(n-1)-1
严谨证明如下:
F[i] =SumZero{1..2i}
F[i-1]=SumZero{1..2i-1}
(2i-1+1)..2i与1..2i-1都为2i-1个数字
F[i]=F[i-1]+(i-1)*2i-2+1
2i-1个数,每个数填满i-1位置,共填(i-1)*2i-1,在这其中
0、1出现的概率是相同的
所以一共是(i-1)*2i-1/2,即(i-1)*2i-2
例如:从1001..(1111)10000
最后3位经历了000->111的过程
而10000还有右数第4的1没有被计算过
所以结果还要加1。
代码如下:
#include <cmath>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main(void) {
int n, tmp, ans;
while(scanf("%d", &n) != EOF) {
ans = tmp = 1;
for(int i=2; i<=n; ++i) {
ans = (ans+ans+tmp)%2007;
tmp = (tmp+tmp+(i-2))%2007;
}
if(n == 0) ans = 0;
if(n == 1) ans = 1;
cout << ans << endl;
}
return 0;
}