HDU 5451 数论

来源:互联网 发布:游族网络2018校园招聘 编辑:程序博客网 时间:2024/06/03 15:42

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5451

本题与HDU 4565类似,构造一个类似fibo的递推式,然后用矩阵快速幂求得需要的那一项,由于此题幂次比较高,我们可以通过寻找循环节——(mod + 1) * (mod - 1)来实现降幂。

据出题人的意思来说,还有一个较大的循环节推法,(p^2- p)(p^2-1)p2p)(p21),这个表示为Zp下矩阵形成的群的大小,也是因此出题人选择了限定了p的大小,

使得循环节不超过LL。

构造fibo递推式的部分,具体解释参见:http://blog.csdn.net/acdreamers/article/details/8994222

AC代码:

//做法类似HDU 4565#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <algorithm>#include <vector>#include <limits.h>#include <queue>#include <map>#include <set>using namespace std;typedef long long LL;#define pll pair<LL, LL>#define pii pair<int, int>#define X first#define Y second#define MAXN 1000010//1e6#define lson l, mid, (rt << 1)#define rson mid + 1, r, (rt << 1 | 1)#define N 3int K;LL mod;const LL a = 5, b = 24;struct Matrix {    int r, c;    LL m[N][N];    Matrix() {}    Matrix(int r,int c) : r(r), c(c) {}    Matrix operator *(const Matrix& B) {        Matrix T(r, B.c);        for(int i = 1; i <= T.r; i++) {            for(int j = 1; j <= T.c; j++) {                LL tt = 0;                for(int k=1; k <= c; k++)                    tt += m[i][k] * B.m[k][j] % mod;                T.m[i][j] = tt % mod;            }        }        return T;    }    Matrix Unit(int h) {        Matrix T(h, h);        memset(T.m, 0, sizeof(T.m));        for(int i = 1; i <= h; i++)            T.m[i][i] = 1;        return T;    }    Matrix Pow(LL n) {        Matrix P = *this, Res = Unit(r);        while(n) {            if(n & 1)                Res = Res * P;            P = P * P;            n >>= 1;        }        return Res;    }} Single;Matrix p, ans;LL power(LL a, LL b, LL MOD) {    LL res = 1LL;    a %= MOD;    while(b) {        if(b & 1) {            res = res * a % MOD;            b--;        }        b >>= 1LL;        a = a * a % MOD;    }    return res;}void init() {    p = Matrix(2,2), ans = Matrix(2, 1);    // 初始矩阵    ans.m[1][1] = (b + a * a % mod) % mod * 2 % mod;    ans.m[2][1] = 2 * a %mod;    // 操作矩阵    p.m[1][1] = ans.m[2][1];    p.m[1][2] = (b - a * a % mod + mod) % mod;    p.m[2][1] = 1;    p.m[2][2] = 0;}int main() {    LL n, x;    int T, cas = 0;    scanf("%d", &T);    while(T--) {        cin >> x >> mod;        LL MOD = (mod + 1) * (mod - 1);        n = power(2, x, MOD);        n = (n + 1) % MOD;        if(n == 1) {            cout << (2 * a - 1 + mod) % mod << endl;            continue;        }        init();        ans = p.Pow(n - 2) * ans;        printf("Case #%d: ", ++cas);        cout << (ans.m[1][1] - 1 + mod) % mod << endl;    }    return 0;}


0 0
原创粉丝点击