HDU 5667 Sequence

指数有递推式,可以通过矩阵快速幂来求解。再用下面这公式快速幂取模即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

long long p,MOD;
long long a, b, c;
long long n;

struct Matrix
{
    long long A[5][5];
    int R, C;
    Matrix operator*(Matrix b);
};

Matrix X, Y, Z;

Matrix Matrix::operator*(Matrix b)
{
    Matrix c;
    memset(c.A, 0, sizeof(c.A));
    int i, j, k;
    for (i = 1; i <= R; i++)
        for (j = 1; j <= C; j++)
            for (k = 1; k <= C; k++)
                c.A[i][j] = (c.A[i][j] + (A[i][k] * b.A[k][j]) % MOD) % MOD;
    c.R = R; c.C = b.C;
    return c;
}

long long mod_exp(long long a, long long b, long long c)
{
    long long res, t;
    res = 1 % c;
    t = a % c;
    while (b)
    {
        if (b & 1) res = res * t % c;
        t = t * t % c;
        b >>= 1;
    }
    return res;
}

void init()
{
    n = n - 2;
    memset(X.A, 0, sizeof X.A);
    memset(Y.A, 0, sizeof Y.A);
    memset(Z.A, 0, sizeof Z.A);

    Z.R = 1; Z.C = 3;
    Z.A[1][1] = 1; Z.A[1][2] = 0; Z.A[1][3] = b%MOD;

    X.R = X.C = 3;
    X.A[1][1] = 1; X.A[1][2] = 0; X.A[1][3] = b%MOD;
    X.A[2][1] = 0; X.A[2][2] = 0; X.A[2][3] = 1;
    X.A[3][1] = 0; X.A[3][2] = 1; X.A[3][3] = c%MOD;

    Y.R = Y.C = 3;
    Y.A[1][1] = 1; Y.A[1][2] = 0; Y.A[1][3] = 0;
    Y.A[2][1] = 0; Y.A[2][2] = 1; Y.A[2][3] = 0;
    Y.A[3][1] = 0; Y.A[3][2] = 0; Y.A[3][3] = 1;
}

void work()
{
    while (n)
    {
        if (n % 2 == 1) Y = Y*X;
        n = n >> 1;
        X = X*X;
    }
    Z = Z*Y;
    printf("%lld\n", mod_exp(a, Z.A[1][3]+MOD, p));
}

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%lld%lld%lld%lld%lld", &n, &a, &b, &c, &p);
        if (n == 1) printf("1\n");
        if (n == 2) printf("%lld\n", mod_exp(a, b, p));
        else
        {
            MOD = p - 1;
            init();
            work();
        }
    }
    return 0;
}
时间: 2024-11-06 23:00:52

HDU 5667 Sequence的相关文章

hdu 5667 Sequence 矩阵快速幂

题目链接:hdu 5667 Sequence 思路:因为fn均为a的幂,所以: 这样我们就可以利用快速幂来计算了 注意: 矩阵要定义为long long,不仅仅因为会爆,还会无限超时 要对a%p==0特判,以为可能出现指数%(p-1)==0的情况,那么在快速幂的时候返回的结果就是1而不是0了 /************************************************************** Problem:hdu 5667 User: youmi Language:

HDU 5667 Sequence(矩阵快速幂+费马小定理)

题意:不好复制,直接上链接http://acm.hdu.edu.cn/showproblem.php?pid=5667 思路: 观察递推式我们可以发现,所有的f_if?i??都是aa的幂次,所以我们可以对f_if?i??取一个以aa为底的loglog,即g_i=log_a\ f_ig?i??=log?a?? f?i?? 那么递推式变成g_i=b+c*g_{i-1}+g_{i-2}g?i??=b+c∗g?i−1??+g?i−2??,这个式子可以矩阵乘法 这题有一个小trick,注意a\ mod\

hdu 5667 Sequence【矩阵快速幂】

Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 285    Accepted Submission(s): 92 Problem Description Holion August will eat every thing he has found. Now there are many foods,but he d

HDU 3397 Sequence operation(线段树)

HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变成1,1变成0 3 a b 查询[a,b]区间1的个数 4 a b 查询[a,b]区间连续1最长的长度 思路:线段树线段合并.须要两个延迟标记一个置为01,一个翻转,然后因为4操作,须要记录左边最长0.1.右边最长0.1,区间最长0.1,然后区间合并去搞就可以 代码: #include <cstdi

HDU 3998 Sequence(经典问题,最长上升子序列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3998 解题报告:求一个数列的最长上升子序列,并求像这样长的不相交的子序列最多有多少个. 我用的是最简单的方法,就是每次求最长上升子序列,然后每次将求得的子序列从数列里面删掉,然后再对剩下的数列求最长上升子序列,如果求得的子序列的长度比第一次求得的长度小的话,就退出.不过我这题卡了很久,原因就是因为用这种方法求的过程中,用到了很多变量,但是没有注意每一步求最长上升子序列的时候都要进行初始化,哎. Vi

hdu 5147 Sequence II(树状数组)

题目链接:hdu 5147 Sequence II 预处理每个位置作为b和c可以组成的对数,然后枚举b的位置计算. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 50005; int N, arr[maxn], fenw[maxn], lef[maxn], rig[maxn]; #d

hdu 3379 Sequence operation(成段更新,区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=3397 线段树很好的题.涉及到的知识点:lazy操作处理异或操作和置01,区间合并. 有五种操作: 0 a b 将[a,b]变为0 1 a b 将[a,b]变为1 2 a b 将[a,b]取反 3 a b 输出[a,b]的1的个数 4 a b 输出[a,b]内最长的连续1的个数 对区间的操作与poj 3225类似.置01与取反是互斥的,一段区间上只能有一个标记,discuss里面也说了取反的时候若递归到区间全为

【线段树】HDU 3397 Sequence operation 区间合并

操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters into '1's in [a , b] 2 a b change all '0's into '1's and change all '1's into '0's in [a, b] Output operations: 3 a b output the number of '1's in [a,

HDU 3397 Sequence operation 线段树

线段树大杂烩~ 各种操作都有,细心点不难1A #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; #define lson rt<<1,l,mid #define rson rt<<1|1,mid + 1,r const int maxn = 1e5 + 10; int lmax[maxn