UVA 10328 Coin Toss

题意:求至少连续的H为k的个数,因为最多有2^100这么多可能,所以要用到大数,这次看了别人的代码写了大数的类,要不分开写函数有太多,还有的是这道题用到了dp,我们可以从总的可能中减去连续的H不超过K-1的可能,所以这道前跟之前的一道题连续W的是差不多的,设dp[i][j]表示前i次连续的H不超过j的个数,,对于第i次,不考虑条件的话是2*dp[i-1][j],那么就还是分两种情况分析,当i==j+1的时候,比如k=4,就是(H,H,H,H,i)显然只有连续j+1个H是不符合条件的,当i>j+1的时候,假设前面有连续j个H,比如连续的不超过4吧,就是这种情况:...T H H H H (i),那么我们在考虑第i位的时候肯定是要考虑当i=H的时候,这中情况是不正确的,而这种情况有f(i-j-2)个,就是T前面已经满足的可能个数

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN = 500;

struct Bigint{
    int f[MAXN],len;
    Bigint(){
        memset(f,0,sizeof(f));
        len = 0;
    }
    void fixlen(Bigint &B,int l){
        while (B.f[l] == 0 && l)
            l--;
        B.len = l + 1;
    }
    void print(){
        for (int i = len-1; i >= 0; i--)
            printf("%d",f[i]);
        printf("\n");
    }
    Bigint operator +(const Bigint &B){
        int i,la=len,lb=B.len;
        Bigint C;
        for (i = 0;; i++){
            if (i < la && i < lb)
                C.f[i] += f[i] + B.f[i];
            else if (i <la)
                C.f[i] += f[i];
            else if (i < lb)
                C.f[i] += B.f[i];
            else break;
            if (C.f[i] > 10){
                C.f[i] -= 10;
                C.f[i+1]++;
            }
        }
        fixlen(C,i);
        return C;
    }
    Bigint operator -(const Bigint &B){
        int i,la=len,lb=B.len;
        Bigint C;
        for (i = 0; i < la; i++){
            C.f[i] += f[i];
            if (i < lb)
                C.f[i] -=B.f[i];
            if (C.f[i] < 0)
                C.f[i+1]--,C.f[i] += 10;
        }
        fixlen(C,i);
        return C;
    }
    Bigint operator *(const int &a){
        Bigint C;
        int i,t=0;
        for (i = 0;; i++){
            if (i >= len && t == 0)
                break;
            if (i < len)
                t = t + f[i] * a;
            C.f[i] = t % 10;
            t /= 10;
        }
        fixlen(C,i);
        return C;
    }
    Bigint(int t){
        f[0] = 0,len = 0;
        while (t){
            f[len++] = t % 10;
            t /= 10;
        }
        if (!len)
            len = 1;
    }
};
Bigint s[MAXN],dp[MAXN][MAXN];

void init1(){
    s[0] = Bigint(1);
    for (int i = 1; i <= 100; i++)
        s[i] = s[i-1] * 2;
}

void init2(){
    int i,j,k;
    for (i = 0; i <= 100; i++)
        dp[i][0] = Bigint(1);
    for (i = 0; i <= 100; i++)
        dp[0][i] = Bigint(1);
    for (i = 1; i <= 100; i++){
        for (j = 1; j <= 100; j++){
            if (i == 1 && j == 1)
                dp[i][j] = 2;
            else if (j <= i){
                dp[i][j] = dp[i-1][j] * 2;
                if (i-j-2 >= 0)
                    dp[i][j] = dp[i][j] - dp[i-j-2][j];
                else if (j < i)
                    dp[i][j] = dp[i][j] - Bigint(1);
            }
            else dp[i][j] = dp[i][j-1];
        }
    }
}

int main(){
    int n,k;
    init1();
    init2();
    Bigint ans;
    while (scanf("%d%d",&n,&k) != EOF){
        ans = s[n] - dp[n][k-1];
        ans.print();
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值