Files
python/TangDou/AcWing_TiGao/T5/QMI/1289.md
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

4.0 KiB
Raw Blame History

##AcWing 1289. 序列的第$K$个数

一、题目描述

BSNY 在学等差数列和等比数列,当已知前三项时,就可以知道是等差数列还是等比数列。

现在给你 整数 序列的前三项,这个序列要么是等差序列,要么是等比序列,你能求出第 k 项的值吗?

如果第 k 项的值太大,对其取模 $200907$。

输入格式 第一行一个整数 $T$,表示有 T 组测试数据;

对于每组测试数据,输入前三项 $a,b,c$,然后输入 $k$。

输出格式 对于每组数据,输出第 k 项取模 200907 的值。

数据范围 1≤T≤100 1≤a≤b≤c≤10^9 1≤k≤10^9

输入样例

2
1 2 3 5
1 2 4 5

输出样例

5
16

二、$Q$:一个数列能不能即是等差数列又是等比数列?

结论:一个数列如果是即是等差又是等比,那么它必然是一个全等数列

证明: 设三个连续数字a\ b \ c, 等差数列,所以a+c=2b ① 等比数列,所以\frac{b}{a}=\frac{c}{b},所以b^2=ac ②

将$a=2b-c$代入② b^2=(2b-c)*c b^2=2bc-c^2 b^2-2bc+c^2=0 (b-c)^2=0 ∴b=c

由此可知,题目中给了数列的前三项,存在可能即是等差又是等比的情况,但此时就是一个全等数列,按哪个规则进行计算都是一样的结果,题目不缺少条件。

三、题意分析

  • 等差数列 公差 d=b-a 第$1$项,$a+0d$ 第$2$项,$a+1d$ 第$3$项,$a+2*d$ ... 第$k$项,应该是$a+(k-1)d$,这个很好求,直接求然后注意取模就行了。

  • 等比数列 公比p=\frac{b}{a} 第$1$项,$ap^0$ 第$2$项,$ap^1$ 第$3$项,$ap^2$ ... 第$k$项,$ap^{k-1}=a*(\frac{b}{a})^{k-1}$

    这东西用 快速幂 就行了

四、理解与思考

数学的题,一般不会真的用代码去暴力计算,通常是推公式,证明。在完成公式的推导后,再用代码进行简单计算,比如2022 $CSP-J$的第二题就是一道公式的推导题,小心下细节就行了。

  • 快速幂:把次数依次化为$2$进制,即可迭代
  • 龟速乘:把当前数变为$2$进制加起来,用于数据很大的情况

五、实现代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 200907;

// 快速幂
int qmi(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}

signed main() {
    int n;
    cin >> n;
    while (n--) {
        int a, b, c, k;
        cin >> a >> b >> c >> k;
        if (a + c == b * 2)                                // 等差
            cout << (a + (b - a) * (k - 1)) % MOD << endl; // 这个比较简单
        else                                               // 等比
            cout << a * qmi(b / a, k - 1) % MOD << endl;   // 这个需要快速幂
    }
}

六、龟速乘版本

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int MOD = 200907;

// 龟速乘,快速加
int qadd(int a, int b) {
    int res = 0;
    while (b) {
        if (b & 1) res = (res + a) % MOD;
        b >>= 1;
        a = (a + a) % MOD;
    }
    return res;
}

// 快速幂
int qmi(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = (res * a) % MOD;
        b >>= 1;
        a = a * a % MOD;
    }
    return res;
}

signed main() {
    int T;
    cin >> T;
    while (T--) {
        int a, b, c, k;
        cin >> a >> b >> c >> k;
        if (a + c == b + b)
            cout << (qadd(b - a, k - 1) + a) % MOD << endl; // 为等差即套公式,首项+公差*(项数-1)
        else
            cout << qmi(b / a, k - 1) * a % MOD << endl; // 等比数列用快速幂算末项
    }
}