AcWing 1289. 序列的第k个数

AcWing 1289. 序列的第K个数

一、题目描述

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

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

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

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

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

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

数据范围
1T100
1abc109
1k109

输入样例

2
1 2 3 5
1 2 4 5

输出样例

5
16

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

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

证明
设三个连续数字a b c,
等差数列,所以a+c=2b
等比数列,所以ba=cb,所以b2=ac

a=2bc代入②
b2=(2bc)c
b2=2bcc2
b22bc+c2=0
(bc)2=0
b=c

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

三、题意分析

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

  • 等比数列
    公比p=ba
    1项,ap0
    2项,ap1
    3项,ap2
    ...
    k项,apk1=a(ba)k1

    这东西用 快速幂 就行了

四、理解与思考

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

  • 快速幂:把次数依次化为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; // 等比数列用快速幂算末项
    }
}
posted @   糖豆爸爸  阅读(91)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
Live2D
点击右上角即可分享
微信分享提示