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


    题目不难懂。式子是一个递推式,并且不难发现f[n]都是a的整数次幂。(f[1]=a0;f[2]=ab;f[3]=ab*f[2]c*f[1]...)

    我们先只看指数部分,设h[n]. 则

    h[1]=0;

    h[2]=b;

    h[3]=b+h[2]*c+h[1];

    h[n]=b+h[n-1]*c+h[n-1].

    h[n]式三个数之和的递推式,所以就可以转化为3x3的矩阵与3x1的矩阵相乘。于是

     h[n]       c  1  b    h[n-1]

    h[n-1]  =  1  0  0  *  h[n-2] 

       1           0  0  1       1

    又根据费马小定理(ap-1%p=1,p是质数且a,p互质)可得:ah[n]%mod=ah[n]%(mod-1)%mod.

    因为 ah[n]%mod= ax*(mod-1)+h[n]%(mod-1)%mod = ax*(mod-1)*ah[n]%(mod-1)%mod = ah[n]%(mod-1)%mod;

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    typedef long long ll;
    ll p;
    struct Mat
    {
        ll mat[3][3];
    };
    Mat Multiply(Mat a, Mat b)
    {
        Mat c;
        memset(c.mat, 0, sizeof(c.mat));
        for(int k = 0; k < 3; ++k)
            for(int i = 0; i < 3; ++i)
                if(a.mat[i][k])
                    for(int j = 0; j < 3; ++j)
                        if(b.mat[k][j])
                            c.mat[i][j] = (c.mat[i][j] +a.mat[i][k] * b.mat[k][j])%(p-1);
        return c;
    }
    Mat QuickPower(Mat a, ll k)
    {
        Mat c;
        memset(c.mat,0,sizeof(c.mat));
        for(int i = 0; i <3; ++i)
            c.mat[i][i]=1;
        for(; k; k >>= 1)
        {
            if(k&1) c = Multiply(c,a);
            a = Multiply(a,a);
        }
        return c;
    }
    ll Powermod(ll a,ll b)
    {
        a%=p;
        ll ans=1;
        for(; b; b>>=1)
        {
            if(b&1) ans=(ans*a)%p;
            a=(a*a)%p;
        }
        return ans;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;
        scanf("%d",&T);
        ll n,a,b,c;
        Mat x;
        while(T--)
        {
            scanf("%I64d%I64d%I64d%I64d%I64d",&n,&a,&b,&c,&p);
            if(n==1)
                printf("1
    ");
            else if(n==2)
                printf("%I64d
    ",Powermod(a,b));
            else
            {
                x.mat[0][0]=c; x.mat[0][1]=1; x.mat[0][2]=b;
                x.mat[1][0]=1; x.mat[1][1]=0; x.mat[1][2]=0;
                x.mat[2][0]=0; x.mat[2][1]=0; x.mat[2][2]=1;
                x=QuickPower(x,n-2);
                ll k=(x.mat[0][0]*b+x.mat[0][2]);
                printf("%I64d
    ",Powermod(a,k));
            }
        }
        return 0;
    }
  • 相关阅读:
    深度优先搜索初尝试-DFS-LakeCounting POJ No.2386
    hdoj-2053-Switch Game
    《算法竞赛入门经典》习题及反思 -<2>
    高精度N的阶乘-N!
    列举一些有所帮助的blog和文章
    hdoj-2039-三角形
    hdoj-2035-人见人爱a^b
    hdoj-2028-Lowest common multiple plus
    hdoj上的一题和程序设计第二次作业的拓展-人见人爱a+b
    程序设计第三次作业---C++计算器雏形
  • 原文地址:https://www.cnblogs.com/pach/p/5990548.html
Copyright © 2020-2023  润新知