You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

##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=0b=c

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

三、题意分析

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

  • 等比数列 公比p=\frac{b}{a}1项,a*p^02项,a*p^13项,a*p^2 ... 第k项,a*p^{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; // 等比数列用快速幂算末项
    }
}