fzoj 1559 Count Zeros(数学:推理)

给定一个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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值