0の左側に1が必要なバイナリ文字列の数

0の左側に1が必要なバイナリ文字列の数

タイトル説明

整数nを指定して、長さnが「0」と「1」の文字で構成されるすべての文字列の中から、「0」の文字の左側に「1」の文字が含まれる文字列の数を求めます。

説明を入力してください:

整数n(1≤n≤2∗ 1 0 7)n(1 \ leq n \ leq2 * 10 ^ 7)を含む行を入力しますn 1n21 07

出力の説明:

返される回答を示す整数を出力します。文字列の数が多いため、オーバーフローする可能性があります。2292 ^ {29}を出力してください。22の後に答え9剰余。

例1
入る
1
出力
1
説明
只有“1”满足
例2
入る
2
出力
2
説明
只有“10”和“11”满足
例3
入る
3
出力
3
説明
只有“101”,“110”,“111”满足

回答:

紙に描くと、最初のいくつかの項目は次のとおりです。12 3 5 8 13…、明らかなフィボナッチシーケンス。データ範囲は少し大きいです、O(n)O(n)O n は合格すべきではなく、行列高速指数を使用すれば完了です。

コード:
#include <cstdio>
#include <cstring>

using namespace std;

const long MOD = 1 << 29;

int n;
long c[2][2];

void matmul(long a[][2], long b[][2]) {
    
    
    memset(c, 0, sizeof c);
    for (int i = 0; i < 2; ++i) {
    
    
        for (int j = 0; j < 2; ++j) {
    
    
            for (int k = 0; k < 2; ++k) {
    
    
                c[i][j] += a[i][k] * b[k][j] % MOD;
                c[i][j] %= MOD;
            }
        }
    }
    memcpy(a, c, sizeof c);
}

int solve(int m) {
    
    
    long ans[][2] = {
    
     {
    
    1,1}, {
    
    1,0} };
    long ret[][2] = {
    
     {
    
    1,0}, {
    
    0,1} };
    
    while (m) {
    
    
        if (m & 1) matmul(ret, ans);
        matmul(ans, ans);
        m >>= 1;
    }
    return ret[0][0];
}

int main(void) {
    
    
    scanf("%d", &n);
    if (n < 3) return 0 * printf("%d\n", n);
    printf("%d\n", solve(n));
    return 0;
}

おすすめ

転載: blog.csdn.net/MIC10086/article/details/108927740