0の左側に1が必要なバイナリ文字列の数
タイトル説明
整数nを指定して、長さnが「0」と「1」の文字で構成されるすべての文字列の中から、「0」の文字の左側に「1」の文字が含まれる文字列の数を求めます。
説明を入力してください:
整数n(1≤n≤2∗ 1 0 7)n(1 \ leq n \ leq2 * 10 ^ 7)を含む行を入力しますn (1≤n≤2∗1 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;
}