PTA Logs Stacking (25分)(Fibonacci数列性质)

5 篇文章 0 订阅

快速倍增

在这里插入图片描述

参考代码

pair<int, int> fib(int n) {
  if (n == 0) return {0, 1};
  auto p = fib(n >> 1);
  int c = p.first * (2 * p.second - p.first);
  int d = p.first * p.first + p.second * p.second;
  if (n & 1)
    return {d, c + d};
  else
    return {c, d};
}

代码即文章来源:https://oi-wiki.org/math/fibonacci/

模意义下周期性

在这里插入图片描述

题目

7-13 Logs Stacking (25分)

Daxinganling produces a lot of timber. Before loading onto trains, the timber jacks will place the logs to some place within no more than two logs’ height first. Looking from the sideway, the figure of a logs stack is as follows:

1575341283(1).png

We have known that the number of logs in each layer is fewer than the lower layer for at least one log, and that in each layer the logs are connected in a line.

In the figure above, there are 4 logs in the bottom layer of the stack, and 3 logs in the top layer of the stack. So the picture shows one kind of figures with 7 logs accumulated together.

Now, given the total number of logs, Little Gyro wants to know how many possible figures there may be.

Input Specification:

There are multiple test cases. The first line of the input contains an integer T (1 ≤ T ≤ 10
​5
​​ ), indicating the number of test cases. For each test case:

Each line contains one integer n (1 ≤ n ≤ 2×10
​9
​​ ), indicating the total number of logs.

Output Specification:

For each test case in the input, you should output the corresponding number of possible figures.

Because the number may be very large, just output the number mod 10000.

Sample Input:

5
1
3
5
7
2000000000

Sample Output:

1
2
5
13
3125

Hint:

In the third sample, you can accumulate 5 logs within such following ways:

First, you can put all the 5 logs at the ground floor.

Then, you can put 4 logs at the bottom layer, and there are 3 positions for the last log to pile up.

After that, you can also put 3 logs at the bottom layer, while the other 2 logs at the top layer.

Above all, you can get 1 + 3 + 1 = 5 figures in order to accumulate 5 logs.

解题

利用上述性质列出递推式,打表发现规律,周期T为75000

代码

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
const int maxn = 1e4 + 2;
const int p = 10000;
int Fib[p];

// 奇数 F(2k + 1) = F(k + 1) ^ 2 + F(k) ^ 2;
// 偶数 F(2k) = F(k)(2F(k + 1) - F(k));
// 该题周期性, 周期为75000

int fib(int n) {
    // if (n == 2 || n == 1) return 1;
    if (n < maxn) return Fib[n];
    int a = fib(n / 2) % p;      // F(k)
    int b = fib(n / 2 + 1) % p;  // F(k + 1)
    if (n & 1) {                 //为奇数
        return (a * a % p + b * b % p) % p;
    } else {  //为偶数
        return a * (2 * b - a + p) % p;
    }
}

int main() {
    Fib[1] = 1;
    for (int i = 2; i < maxn; i++) {
        Fib[i] = (Fib[i - 1] + Fib[i - 2]) % p;
    }

    int T, n;
    cin >> T;
    while (T--) {
        scanf("%d", &n);
        cout << fib(n % 75000) << endl;
    }

    system("pause");
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值