您的位置:首页 > 其它

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

2015-09-20 01:29 405 查看

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 (0≤x<232) and
a given prime number M (M≤46337),
print [y]%M.
([y] means
the integer part of y)



Input

An integer T (1<T≤1000),
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

7
0 46337
1 46337
3 46337
1 46337
21 46337
321 46337
4321 46337




Sample Output

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




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

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

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

找循环节解析链接:点我

裸题链接:点我

AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#define LL long long
struct 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: