poj 1953 World Cup Noise (数学:推导)

本文探讨了如何在0到2^n-1之间计算没有连续1出现的数的数量,并通过递推公式dp[i] = dp[i-1] + dp[i-2] + 2^(i-2)来解决这一问题。

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

题目给出n,问你0-(2^n-1)之间存在多少没有连续1出现的数

先找1连续出现数的个数

列出几个数就可以找到规律了

0:【0】0个

1:【00】【01】0个

2:【00】【01】【10】【11】0+0+1 = 1个

3:【00】【01】【10】【11】

      【100】【101】【110】【111】

上下两行对比即可发现规律0+1+2 = 3

对于dp【i】,把0-(2^i-1)等分成前后两段

前一段即为dp【i-1】,后一段的前半部分为dp【i-2】,后半段的后半部分必然存在连续1

所以dp【i】 = dp【i-1】+dp【i-2】+pow(2,i-2)

代码如下:

#include <cstdio>
#define LL long long
using namespace std;

LL dp[50];

void init() {
    LL tmp = 1ll;
    dp[0] = dp[1] = 0;
    for(int i=2; i<=45; ++i) {
        dp[i] = dp[i-1]+dp[i-2]+tmp;
        tmp *= 2;
    }

    tmp = 1ll;
    for(int i=0; i<=45; ++i) {
        dp[i] = tmp - dp[i];
        tmp *= 2; 
    }
}

int main(void) {
    int T, n;
    init();
    scanf("%d", &T);
    for(int t=1; t<=T; ++t) {
        scanf("%d", &n);
        printf("Scenario #%d:\n%lld\n\n", t, dp[n]);
    }
    return 0;
}

/*

   1111 1110 1101 1100 1011 1010 1001 1000 0111 0110 0101 0100 0011 0010 0001 0000
   
   dp[0] = 0;
   dp[1] = 0;
   dp[2] = 1;
   dp[3] = dp[1]+dp[2]+2^1 = 3;
   dp[4] = dp[2]+dp[3]+2^2 = 8;
   dp[5] = dp[3]+dp[4]+2^3 = 19;

   dp[1] = 0;
   dp[2] += dp[0]+dp[0];
   dp[3] += dp[2]+dp[2];
   dp[4] += dp[3]+dp[3];

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值