1. 程式人生 > 實用技巧 >習題:Product Oriented Recurrence(矩陣快速冪)

習題:Product Oriented Recurrence(矩陣快速冪)

題目

傳送門

思路

我們將乘法轉換成冪的加法即可

注意指數取模是取模\(\phi(1e9+7)\)

其實就是\(1e9+6\)

程式碼

#include<iostream>
#include<cstring>
using namespace std;
const int mod=1e9+6;
long long n,f1,f2,f3,c;
struct mat
{
    int n,m;
    long long a[6][6];
    mat()
    {
        n=m=0;
        memset(a,0,sizeof(a));
    }
    friend mat operator * (const mat &a,const mat &b)
    {
        mat c;
        c.n=a.n;
        c.m=b.m;
        for(int i=1;i<=a.n;i++)
            for(int k=1;k<=a.m;k++)
                for(int j=1;j<=b.m;j++)
                    c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
        return c;
    }
}bas[5],acc[5];
long long qkpow(long long a,long long b)
{
    if(b==0)
        return 1;
    if(b==1)
        return a%(mod+1);
    long long t=qkpow(a,b/2);
    t=t*t%(mod+1);
    if(b%2==1)
        t=t*a%(mod+1);
    return t;
}
mat qkpow(mat a,long long b)
{
    if(b==1)
        return a;
    mat t=qkpow(a,b/2);
    t=t*t;
    if(b%2==1)
        t=t*a;
    return t;
}
int main()
{
    cin>>n>>f1>>f2>>f3>>c;
    bas[1].n=bas[2].n=bas[3].n=3;
    bas[1].m=bas[2].m=bas[3].m=1;
    bas[1].a[1][1]=bas[2].a[2][1]=bas[3].a[3][1]=1;
    acc[1].n=acc[1].m=3;
    acc[1].a[1][2]=acc[1].a[2][3]=acc[1].a[3][1]=acc[1].a[3][2]=acc[1].a[3][3]=1;
    acc[2]=acc[1];
    acc[3]=acc[1];
    
    bas[4].n=5;
    bas[4].m=1;
    bas[4].a[4][1]=bas[4].a[5][1]=2;
    acc[4].n=acc[4].m=5;
    acc[4].a[1][2]=acc[4].a[2][3]=acc[4].a[3][1]=acc[4].a[3][2]=acc[4].a[3][3]=acc[4].a[3][4]=acc[4].a[4][4]=acc[4].a[4][5]=acc[4].a[5][5]=1;

    bas[1]=qkpow(acc[1],n-1)*bas[1];
    bas[2]=qkpow(acc[2],n-1)*bas[2];
    bas[3]=qkpow(acc[3],n-1)*bas[3];
    bas[4]=qkpow(acc[4],n-1)*bas[4];
    /*for(int i=1;i<=4;i++)
        cout<<bas[i].a[1][1]<<' ';
    cout<<endl;*/
    cout<<qkpow(f1,bas[1].a[1][1])*qkpow(f2,bas[2].a[1][1])%(mod+1)*qkpow(f3,bas[3].a[1][1])%(mod+1)*qkpow(c,bas[4].a[1][1])%(mod+1);
    return 0;
}
/*
100
010
001
111

1    2
2 -> 3
3    4

*/
/*
{2x-6}->{2(x+1)-6}
{2x-1}->{2x-6+2}

2:0     0 
3:0 ->  2
4:2 ->  4


1  :0 01000
2  :0 00100
3  :0 11110
d4 :2 00011
bas:2 00001
*/