数学-快速幂与矩阵快速幂

1.A sequence of numbers

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3670

题解:这是一道隐藏的快速幂的模板题,从数据我们就可以知道。对该题进行分析,如何判别是等差or等比,通过比较a[2]-a[1]==a[3]-a[2]如果相等,则为等差

否则a[2]/a[1]==a[3]/a[2],就为等比,然后利用快速幂来解决等比。

代码:

#include
using namespace std;
typedef long long ll;
const int mod=200907;
ll N,K;
ll a[10];

ll fastPow(ll a,ll n)
{
    ll res=1;
    while(n)
    {
        if(n&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        n>>=1;
    }
    return res;
}

int main()
{
    ll i,j;
    cin>>N;
    while(N--)
    {
        for(i=1;i<=3;i++)
            cin>>a[i];
        cin>>K;
        if(a[2]-a[1]==a[3]-a[2])
        {
            cout<<(a[1]+((a[2]-a[1])%mod)*((K-1)%mod))%mod<<endl;
        }
        else if(a[2]/a[1]==a[3]/a[2])
        {
            ll q=a[2]/a[1];
            ll c=K-1;
            cout<<(fastPow(q,c)*a[1])%mod<<endl;
        }
    }
    return 0;
}

 

2.Rightmost Digit

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1061

题解:这是一道典型的快速幂,只不过有一点需要注意,不要再完成运算后再取模,应该边运算边取模,否则会TLE

代码:

#include
using namespace std;
typedef long long ll;
ll T;

ll fastPow(ll a,ll n)
{
    ll res=1;
    while(n)
    {
        if(n&1)
            res=(res*a)%10;
        a=(a*a)%10;
        n>>=1;
    }
    res=res%10;
    return res;
}

int main()
{
    ll i,j,N;
    cin>>T;
    while(T--)
    {
        cin>>N;
        ll ans=fastPow(N,N);
        cout<endl;
    }
    return 0;
}

 

3.矩阵快速幂

题目:https://www.luogu.com.cn/problem/P3390

题解:一道入门级矩阵快速幂的运算

代码:

#include
#include
using namespace std;
const int MAXN=110;
const int MOD=1e9+7;
typedef long long ll;
struct Matrix{
    ll m[MAXN][MAXN];
    Matrix()
    {
        memset(m,0,sizeof(m));
    }
};
Matrix Multi(Matrix a,Matrix b)
{
    Matrix res;
    for(ll i=0;i)
    {
        for(ll j=0;j)
        {
            for(ll k=0;k)
                res.m[i][j]=(res.m[i][j]+a.m[i][k]*b.m[k][j])%MOD;
        }
    }
    return res;
}
Matrix fastm(Matrix a,ll n)
{
    Matrix res;
    for(ll i=0;i)
        res.m[i][i]=1;
    while(n)
    {
        if(n&1)
            res=Multi(res,a);
        a=Multi(a,a);
        n>>=1;
    }
    return res;
}

int main()
{
    ll n,k,i,j;
    Matrix s;
    cin>>n>>k;
    for(i=0;i)
    {
        for(j=0;j)
            cin>>s.m[i][j];
    }
    s=fastm(s,k);
    for(i=0;i)
    {
        for(j=0;j)
            cout<" ";
        cout<<endl;
    }
    return 0;
}

 

4.矩阵加速

题目:https://www.luogu.com.cn/problem/P1939

题解:一道需要求出对应矩阵的矩阵快速幂的运算。

分析一下:

a[n]=1*a[n-1]+0*a[n-2]+1*a[n-3]

a[n-1]=1*a[n-1]+0*a[n-2]+0*a[n-3]

a[n-2]=0*a[n-1]+1*a[n-2]+0*a[n-3]

 

因此,我们可以总结出:

数学-快速幂与矩阵快速幂_第1张图片

 

进而,对其进行推到,因为我们已知a1=a2=a3=1,所以尽可能使右边的行列式替换成已知数,因此,最终的公式为:

数学-快速幂与矩阵快速幂_第2张图片

 

 这样我们最终要求的就是an在数组中的位置为res.m[0][0],然后我们利用矩阵快速幂来求解行列式的n-3次方的值乘以行列式即可

其中,需要注意的是MAXN=3还有对于小于等于3的进行特判,否则会TLE的

代码:

#include
#include
using namespace std;
typedef long long ll;
const int MAXN=3;
const long long  MOD=1e9+7;
struct Matrix
{
    ll m[MAXN][MAXN];
    Matrix()
    {
        memset(m,0,sizeof(m));
    }
};
Matrix Multi(Matrix a,Matrix b)
{
    Matrix res;
    for(ll i=0;i)
    {
        for(ll j=0;j)
        {
            for(ll k=0;k)
                res.m[i][j]=(res.m[i][j]+a.m[i][k]%MOD*b.m[k][j]%MOD)%MOD;
            res.m[i][j]%=MOD;
        }
    }
    return res;
}

Matrix fastm(Matrix a,ll n)
{
    Matrix res;
    for(ll i=0;i)
        res.m[i][i]=1;
    while(n)
    {
        if(n&1)
            res=Multi(res,a);
        a=Multi(a,a);
        n>>=1;
    }
    return res;
}

int main()
{
    ll i,j,t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        if(n <= 3) {
            printf("1\n");
            continue;
        }
        Matrix k,s,res;
        k.m[0][0]=1;
        k.m[1][0]=1;
        k.m[2][0]=1;

        s.m[0][0]=1;s.m[0][1]=0;s.m[0][2]=1;
        s.m[1][0]=1;s.m[1][1]=0;s.m[1][2]=0;
        s.m[2][0]=0;s.m[2][1]=1;s.m[2][2]=0;

        s=fastm(s,n-3);
        res=Multi(s,k);
        cout<0][0]<<endl;
    }
    return 0;
}

 

你可能感兴趣的:(数学-快速幂与矩阵快速幂)