递推式题解

本文在此处同步更新
题目
在这里插入图片描述

样例

4
2 3 100
1 4 1000
3 3 1000000000
9 123456 78987

54
4
299
12153

首先我们可以推出如下式子

  1. a n = x a n − 1 + y a n − 2 a_n=xa_{n-1}+ya_{n-2} an=xan1+yan2

  2. a n 2 = x 2 a n − 1 2 + 2 x y a n − 1 a n − 2 + y 2 a n − 2 2 a_n^2=x^2 a_{n-1}^2+2xya_{n-1}a_{n-2}+y^2a_{n-2}^2 an2=x2an12+2xyan1an2+y2an22

  3. s n = s n − 1 + a n 2 s_{n}=s_{n-1}+a_n^2 sn=sn1+an2

然后发现,要求 s n s_{n} sn,先要知道 a n 2 a_n^2 an2,要知道 a n 2 a_n^2 an2,还要知道 a n − 1 a n − 2 a_{n-1}a_{n-2} an1an2

虽然我们可以先求出 s n s_{n} sn a n 2 a_n^2 an2以及 a n + 1 2 a_{n+1}^2 an+12(前2个都告诉你了),可 a n + 2 a_{n+2} an+2呢?

那就得知道 a n a n + 1 a_na_{n+1} anan+1

可得 a n a n + 1 = a n ( x a n + y a n − 1 ) = x a n 2 + y a n a n − 1 a_na_{n+1}=a_n(xa_n+ya_{n-1})=xa_{n}^2+ya_{n}a_{n-1} anan+1=an(xan+yan1)=xan2+yanan1

a n 2 a_{n}^2 an2已知

a n a n − 1 a_{n}a_{n-1} anan1可以通过同样的式子(除了初始化时,不过那可以直接算)求出来

于是我们知道了怎么构造 a n s ans ans矩阵
{ s [ n − 1 ] , a 1 a [ n ] 2 , a 2 a [ n − 1 ] 2 , a 3 a [ n ] ∗ a [ n − 1 ] a 4 } \{\\ s[n-1], a1 \\ a[n]^2, a2 \\ a[n-1]^2, a3 \\ a[n]*a[n-1] a4 \\ \} {s[n1],a1a[n]2,a2a[n1]2,a3a[n]a[n1]a4}
至于 b a s e base base矩阵,可以直接根据上面的算

第一项可以直接加法得到,第三项则直接由原来第二项变换过来

第二、第四项的简化式子如下

a [ n + 1 ] 2 = x 2 ∗ a 2 + y 2 ∗ a 3 + 2 x y ∗ a 4 a[n+1]^2=x^2*a2+y^2*a3+2xy*a4 a[n+1]2=x2a2+y2a3+2xya4
a [ n ] a [ n + 1 ] = x ∗ a [ n ] 2 + y ∗ a [ n ] ∗ a [ n − 1 ] = x ∗ a 2 + y ∗ a 4 a[n]a[n+1]=x*a[n]^2+y*a[n]*a[n-1]=x*a2+y*a4 a[n]a[n+1]=xa[n]2+ya[n]a[n1]=xa2+ya4
可得 b a s e base base
{ 1     1     0     0 0   x 2   y 2   2 x y 0     1     0     0 0     x     0     y } \{\\ 1~~~1~~~0~~~0\\ 0~x^2~y^2~2xy\\ 0~~~1~~~0~~~0\\ 0~~~x~~~0~~~y\\ \} {1   1   0   00 x2 y2 2xy0   1   0   00   x   0   y}
剩下的主要是预处理与快速幂
还有 不开long long见祖宗

所有预处理记得都取模一下,不然 long long会炸

快速幂有点烦,其他还好

//写得有些丑,见谅
#pragma GCC optimize(1, "inline", "Ofast")
#pragma GCC optimize(2, "inline", "Ofast")
#pragma GCC optimize(3, "inline", "Ofast")
// #include <bits/extc++.h>
#include <bits/stdc++.h>
#define memery() std::cerr << "The memory is " << (&ed - &st) / 1024.0 / 1024 << "MB." << std::endl
//#include <"C:\Users\admin\Documents\myhead\fstio.hpp">
//#include <"C:\Users\admin\Documents\myhead\def.hpp">
//#include <"C:\Users\admin\Documents\myhead\help.h">
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;
using namespace std;
#define int long long
//变量区
bool st;
const int N = 5e6 + 7;
//please write sth.
int tk, a[4][4], b[4][4], c[4][4], n, m, x;
bool ed;
//函数区
void input()
{
    //please write sth.
    cin >> x >> n >> m;
}
void mul1(int b[4][4])
{
    //5 4
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 1; j++)
            c[i][j] = 0;
    for (int k = 0; k < 4; k++)
        for (int i = 0; i < 4; i++) //0 0  0 x  x 0
            for (int j = 0; j < 1; j++)
                (c[i][j] += ((1ll * b[i][k] * a[k][j]) % m + m) % m) %= m;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 1; j++)
            a[i][j] = c[i][j];
}
void mul2(int a[4][4], int b[4][4], int c[4][4])
{
    //5 4
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            c[i][j] = 0;
    for (int k = 0; k < 4; k++)
        for (int i = 0; i < 4; i++) //0 0  0 x  x 0
            for (int j = 0; j < 4; j++)
                (c[i][j] += ((1ll * a[i][k] * b[k][j]) % m + m) % m) %= m;
}
void k(int a[4][4], int b[4][4])
{
    int xx[4][4];
    mul2(a, b, xx);
    for (int i = 0; i < 4; i++) //0 0  0 x  x 0
        for (int j = 0; j < 4; j++)
            a[i][j] = xx[i][j];
}
void work()
{
    //please write sth.
    a[0][0] = 1;
    a[1][0] = (1ll * x * x) % m;
    a[2][0] = 1;
    a[3][0] = x;
    x *= 2, x %= m;
    int y = -1;
    int bb[4][4] = { { 1, 1, 0, 0 },
        { 0, (1ll * x * x) % m, (1ll * y * y) % m, (2ll * x * y) % m },
        { 0, 1, 0, 0 },
        { 0, x, 0, y } };
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            b[i][j] = bb[i][j];
    n--;
    for (; n; n >>= 1, k(b, b))
        if (n & 1)
            mul1(b);
}
void output()
{
    //please write sth.
    if (n == 1)
        cout << 1 << endl;
    else
        cout << a[0][0] << endl;
}
//主函数
signed main()
{
    //memory();
    std::ios::sync_with_stdio(0);
    std::cin.tie(), std::cout.tie();
    cin >> tk;
    while (tk--) {
        input();
        work();
        output();
    }
}
  • 29
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值