hdoj 5451 Best Solver 【求循环节 + 矩阵快速幂】

来源:互联网 发布:高铁抢票软件 编辑:程序博客网 时间:2024/06/01 08:32



Best Solver

Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 229    Accepted Submission(s): 98


Problem Description
The so-called best problem solver can easily solve this problem, with his/her childhood sweetheart.

It is known that y=(5+26)1+2x.
For a given integer x (0x<232) and a given prime number M (M46337), print [y]%M. ([y] means the integer part of y)
 

Input
An integer T (1<T1000), indicating there are T test cases.
Following are T lines, each containing two integers x and M, as introduced above.
 

Output
The output contains exactly T lines.
Each line contains an integer representing [y]%M.
 

Sample Input
70 463371 463373 463371 4633721 46337321 463374321 46337
 

Sample Output
Case #1: 97Case #2: 969Case #3: 16537Case #4: 969Case #5: 40453Case #6: 10211Case #7: 17947
 



比赛时卡在这道题了,醉了。


打表找出循环节loop = (M - 1) * (M + 1),然后求解 2^n % loop,下面就是矩阵快速幂裸题了。


提交6次代码才过,CE5次。杭电要炸了。。。


找循环节解析链接:点我

裸题链接:点我



AC代码:


#include <cstdio>#include <cstring>#include <cmath>#define LL long longstruct Matrix{    LL a[3][3];};Matrix ori, res;LL M;void init(){    memset(ori.a, 0, sizeof(ori.a));    memset(res.a, 0, sizeof(res.a));    for(int i = 0; i < 2; i++)        res.a[i][i] = 1;    ori.a[0][0] = 5, ori.a[0][1] = 2;    ori.a[1][0] = 12, ori.a[1][1] = 5;}Matrix muitl(Matrix x, Matrix y){    Matrix z;    memset(z.a, 0, sizeof(z.a));    for(int i = 0; i < 2; i++)    {        for(int k = 0; k < 2; k++)        {            if(x.a[i][k] == 0) continue;            for(int j = 0; j < 2; j++)                z.a[i][j] = (z.a[i][j] + (x.a[i][k] * y.a[k][j]) % M) % M;        }    }    return z;}LL F[3], ans[3];int k = 1;void solve(LL n){    while(n)    {        if(n & 1)            res = muitl(ori, res);        ori = muitl(ori, ori);        n >>= 1;    }    for(int i = 0; i < 2; i++)    {        ans[i] = 0;        for(int k = 0; k < 2; k++)            ans[i] = (ans[i] + (F[k] * res.a[k][i]) % M) % M;    }    printf("Case #%d: %lld\n", k++, (2*ans[0] - 1) % M);}LL pow_mod(LL a, LL p, LL n){    if(p == 0) return 1;    LL ans = pow_mod(a, p/2, n);    ans = ans * ans % n;    if(p % 2 == 1) ans = ans * a % n;    return ans;}int main(){    int t;    LL n, N;    F[0] = 5, F[1] = 2;    scanf("%d", &t);    while(t--)    {        scanf("%lld%lld", &n, &M);        LL loop = (M+1) * (M-1);//循环节        LL N = pow_mod(2, n, loop) + 1;//快速幂 求解2^n % loop        init();//构造矩阵        solve(N-1);//矩阵快速幂    }    return 0;}


0 0