快速幂与矩阵乘法

快速幂与矩阵乘法

快速幂 算法的时间复杂度推导:n/2^k=1    => n=2^k  => logn=log2^k => k=logn 故 O(logn)   .2018-9-17 22:28

P1226 【模板】快速幂||取余运算

在线测评地址:https://www.luogu.org/problemnew/show/P1226

AC代码如下:

//P1226 【模板】快速幂||取余运算
//https://www.luogu.org/problemnew/show/P1226
//提交,测试点7,WA
//https://www.luogu.org/discuss/show?postid=56034看了讨论,发现
//输入:1 0 1 正确输出:1^0 mod 1=0 你的输出:1^0 mod 1=1
//总而言之,对洛谷加强数据(测试点7)表示不满,有些牛角尖了。2018-9-17 22:52
//将printf("%lld^%lld mod %lld=%lld\n",b,p,k,quick_power(b,p,k));改成
//printf("%lld^%lld mod %lld=%lld\n",b,p,k,quick_power(b,p,k)%k); 
//提交AC。2018-9-17 22:53 
#include <stdio.h>
#define LL long long
LL quick_power(LL b,LL p,LL k){
    LL ans=1;
    while(p){
        if(p&1)ans=ans*b%k;
        b=b*b%k;
        p>>=1;
    }
    return ans;
}
int main(){
    LL b,p,k;
    scanf("%lld%lld%lld",&b,&p,&k);
    printf("%lld^%lld mod %lld=%lld\n",b,p,k,quick_power(b,p,k)%k);
    return 0;
}

//P1965 转圈游戏
//在线测评地址https://www.luogu.org/problemnew/show/P1965
//动笔,模拟,举个比样例更简单的例子,发现如下规律
//x1=(x0+m)%n
//x2=(x1+m)%n   => x2=(x0+2m)%n
//x3=(x3+m)%n   => x3=(x0+3m)%n
//xq=(x0+qm)%n  => xq=(x0+qm%n)%n   => xq=(x0+q%n*m)%q
//q=10^k    10^109 采用 快速幂 算法的时间复杂度 log(10^10^9) 大致 10^9 还是有些险
//快速幂,稳妥起见,不采用int 采用long long
//样例通过,一次成功,提交AC。2018-9-21
#include <stdio.h>
#define LL long long
LL quickPower(LL a,LL b,LL p){
    LL ans=1;
    while(b){
        if(b&1)ans=(ans*a)%p;
        a=(a*a)%p;
        b>>=1;
    }
    return ans;
}
int main(){
    LL n,m,k,x,ans;
    scanf("%lld%lld%lld%lld",&n,&m,&k,&x);//此处写成 scanf("%d%d%d%d",&n,&m,&k,&x);
    ans=quickPower(10,k,n);
    ans=(x+ans*m)%n;
    printf("%lld\n",ans);
    return 0;
}

矩阵乘法

//P3390 【模板】矩阵快速幂
//在线测评地址https://www.luogu.org/problemnew/show/P3390
//提交,有些担心,但看到,测试点2-9 AC了,总算放下些心。测试点1,10卡住了 
//代码没做任何修改,再次提交,竟然AC了。够神奇的。2018-9-18 19:48 
#include <stdio.h>
#include <string.h>
#define LL long long
#define maxn 110
#define mod 1000000007
LL a[maxn][maxn],f[maxn][maxn],c[maxn][maxn],n,k;
void mul(){//此处写成 void mul(LL f[][],LL a[][])
    LL i,j,k;
    memset(c,0,sizeof(c));
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            for(k=1;k<=n;k++)
                c[i][j]=(c[i][j]+a[i][k]*f[k][j])%mod;
    memcpy(f,c,sizeof(c));
}
void mulself(){//此处写成 void mulself(LL a[][])
    LL i,j,k;
    memset(c,0,sizeof(c));
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            for(k=1;k<=n;k++)
                c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
    memcpy(a,c,sizeof(c));
}
void quick_power(){//此处写成 void quick_power(LL a[][],LL k)
    while(k){
        if(k&1)mul();
        mulself();
        k>>=1;
    }
}
int main(){
    LL i,j;
    scanf("%lld%lld",&n,&k);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            scanf("%lld",&a[i][j]);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(i==j)
                f[i][j]=1;//初始化为单位矩阵// 忘记了 初始化 
            else 
                f[i][j]=0;
    quick_power();
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++)
            printf("%lld ",f[i][j]);
        printf("\n");
    }
    return 0;
}

//P1962 斐波那契数列
//在线测评地址https://www.luogu.org/problemnew/show/P1962
//[{f[2],f[1]}]*[{1,1},{1,0}] 与 [{1,1},{1,0}]*[{f[2]},{f[1]}] 从易算角度 选择后者
//该题要注意,数组的处理,起始选 0脚标开始 还是 1脚标开始,要特别注意。 2018-9-21
#include <stdio.h>
#include <string.h>
#define mod 1000000007
#define LL long long
LL f[2]={1,1},g[2],a[2][2]={{1,1},{1,0}},d[2][2]={{1,0},{0,1}},c[2][2],n;//d 此刻 单位矩阵
void mul(){//a*d
    LL i,j,k;
    memset(c,0,sizeof(c));
    for(i=0;i<2;i++)//此处写成 for(i=1;i<=2;i++)
        for(j=0;j<2;j++)
            for(k=0;k<2;k++)
                c[i][j]=(c[i][j]+a[i][k]*d[k][j])%mod;
    memcpy(d,c,sizeof(c));
}
void mulself(){//a*a
    LL i,j,k;
    memset(c,0,sizeof(c));
    for(i=0;i<2;i++)
        for(j=0;j<2;j++)
            for(k=0;k<2;k++)
                c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
    memcpy(a,c,sizeof(c));
}
void quickPower(LL b){
    while(b){
        if(b&1)mul();
        mulself();
        b>>=1;
    }
}
void mulf(){
    LL i,j;
    memset(g,0,sizeof(g));
    for(i=0;i<2;i++)
        for(j=0;j<2;j++)
            g[i]=(g[i]+d[i][j]*f[j])%mod;
    memcpy(f,g,sizeof(g));
}
int main(){
    scanf("%lld",&n);
    if(n==1||n==2)printf("1\n");//特判
    else{
        quickPower(n-2);
        mulf();
        printf("%lld\n",f[0]);
    }
    return 0;
}

//P1067 Warcraft III 守望者的烦恼
//决定重写该题代码,重新设计矩阵,以下内容为重新设计。2018-9-22 16:07 
//在线测评地址https://vijos.org/p/1067
//若有该题(1190:上台阶,在线测评地址http://ybt.ssoier.cn:8088/problem_show.php?pid=1190)基础,此题的递推公式不成问题。
//该题递推公式:f(n)=f(n-1)+f(n-2)+...+f(n-k)
//f(0)=1,f(1)=1,f(2)=f(2-1)+f(2-2),f(3)=f(3-1)+f(3-2)+f(3-3),f(4)=f(4-1)+f(4-2)+f(4-3)+f(4-4)
//f(k)=f(k-1)+f(k-2)+...+f(k-k)
//注意:f(1),f(2),...,f(k-1),f(k),通过两重循环可求得
//f(k+1)=f(k)+f(k-1)+...+f(1)
//f(k+2)=f(k+1)+f(k)+...+f(2)
//f(k+1),f(k+2),...,f(n-1),f(n)需通过矩阵乘法,才可快速求得
//0 1 0...0 0 0
//0 0 1...0 0 0
//... ... ...
//0 0 0...0 0 1
//1 1 ... 1 1 1
//构造 k 阶矩阵A如上?
//A*[f(1),f(2),...,f(k-1),f(k)]=[f(2),f(3),...,f(k),f(1)+f(2)+...+f(k-1)+f(k)]=[f(2),f(3),...,f(k),f(k+1)];
//故A^(n-k)*[f(1),f(2),...,f(k-1),f(k)]=[f(n-k),...,f(n-1),f(n)]
//编写完毕,样例测试后,提交,一把AC。相当满意目前矩阵的构造方法。2018-9-22 16:29 
#include <stdio.h>
#include <string.h>
#define mod 7777777
#define LL long long
LL k,n,A[15][15],c[15][15],f[15],g[15];
void mul(){
    LL i,j;
    memset(g,0,sizeof(g));
    for(i=1;i<=k;i++)
        for(j=1;j<=k;j++)
            g[i]=(g[i]+A[i][j]*f[j])%mod;
    memcpy(f,g,sizeof(g));
}
void mulself(){
    LL i,j,p;
    memset(c,0,sizeof(c));
    for(i=1;i<=k;i++)
        for(j=1;j<=k;j++)
            for(p=1;p<=k;p++)
                c[i][j]=(c[i][j]+A[i][p]*A[p][j])%mod;
    memcpy(A,c,sizeof(c));
}
void quickPower(LL b){
    while(b){
        if(b&1)mul();
        mulself();
        b>>=1;
    }
}
int main(){
    LL i,j;
    memset(A,0,sizeof(A));
    memset(f,0,sizeof(f));
    scanf("%lld%lld",&k,&n);
    for(j=1;j<=k;j++)A[k][j]=1;
    for(i=1;i<=k-1;i++)A[i][i+1]=1;
    f[1]=f[0]=1;
    for(i=2;i<=k;i++)
        for(j=0;j<i;j++)
            f[i]=(f[i]+f[j])%mod;
    if(n<=k)printf("%lld\n",f[n]);
    else{
        quickPower(n-k);
        printf("%lld\n",f[k]);
    }
    return 0;
}
 

//P1067 Warcraft III 守望者的烦恼
//在线测评地址https://vijos.org/p/1067
//若有该题(1190:上台阶,在线测评地址http://ybt.ssoier.cn:8088/problem_show.php?pid=1190)基础,此题的递推公式不成问题。
//该题递推公式:f(n)=f(n-1)+f(n-2)+...+f(n-k)
//f(0)=1,f(1)=1,f(2)=f(2-1)+f(2-2),f(3)=f(3-1)+f(3-2)+f(3-3),f(4)=f(4-1)+f(4-2)+f(4-3)+f(4-4)
//f(k)=f(k-1)+f(k-2)+...+f(k-k)
//注意:f(1),f(2),...,f(k-1),f(k),通过两重循环可求得 
//f(k+1)=f(k)+f(k-1)+...+f(1)
//f(k+2)=f(k+1)+f(k)+...+f(2)
//f(k+1),f(k+2),...,f(n-1),f(n)需通过矩阵乘法,才可快速求得
//1 1 ... 1 1
//1 0 ... 0 0
//0 1 ... 0 0
//... ... ...
//0 0 ... 1 0
//构造 k 阶矩阵A如上 
//A*[f(k),f(k-1),...,f(1)]=[f(k)+f(k-1)+...+f(1),f(k),...,f(2)]=[f(k+1),f(k),...,f(2)]; 
//故A^(n-k)*[f(k),f(k-1),...,f(1)]=[f(n),f(n-1),...,f(n-k)] 
//提交,测试点3,4AC,测试点2 Wrong Answer,其余测试点 Runtime Error
//修改,for(i=2;i<=k;i++)//此处写成 for(i=2;i<=n;i++),提交,只剩测试点2 Wrong Answer。
//查了讨论,发现 WA#2了的自己测k=n的吧...。
//继续修改,printf("%lld\n",f[k-n+1]);//此处写成 printf("%lld\n",f[n]);提交AC。
//感觉程序在矩阵的元素顺序上挺别扭,还是要改改的。 2018-9-22 13:26 

//该种构造的矩阵,编写程序容易出错,难以一次AC,决定重新构造矩阵,重新编写代码,详见上面的方法。2018-9-22 15:35
#include <stdio.h>
#include <string.h>
#define mod 7777777
#define LL long long
LL k,n,f[15],g[15],A[15][15],c[15][15];
void mulself(){
    LL i,j,p;
    memset(c,0,sizeof(c));
    for(i=1;i<=k;i++)
        for(j=1;j<=k;j++)
            for(p=1;p<=k;p++)
                c[i][j]=(c[i][j]+A[i][p]*A[p][j])%mod;
    memcpy(A,c,sizeof(c));
}
void mul(){
    LL i,j;
    memset(g,0,sizeof(g));
    for(i=1;i<=k;i++)
        for(j=1;j<=k;j++)
            g[i]=(g[i]+A[i][j]*f[j])%mod;
    memcpy(f,g,sizeof(g));
}
void quickPower(LL b){
    while(b){
        if(b&1)mul();
        mulself();
        b>>=1;
    }
}
int main(){
    LL i,j;
    memset(f,0,sizeof(f));
    memset(A,0,sizeof(A));
    memset(g,0,sizeof(g));
    scanf("%lld%lld",&k,&n);
    g[1]=g[0]=1;
    for(i=2;i<=k;i++)//此处写成 for(i=2;i<=n;i++)
        for(j=0;j<i;j++)
            g[i]=(g[i]+g[j])%mod;//f[i]初始化 
    for(i=1;i<=k;i++)f[i]=g[k-i+1];
    for(j=1;j<=k;j++)A[1][j]=1;
    for(i=2;i<=k;i++)A[i][i-1]=1;//此处写成A[i][i+1]=1,不过马上在接下来的测试中发现了//A[i][j]初始化
    if(n<=k)printf("%lld\n",f[k-n+1]);//此处写成 printf("%lld\n",f[n]);
    else{
        quickPower(n-k);
        printf("%lld\n",f[1]);
    } 
    return 0;
}
//Matrix Power Series 
//在线测评地址https://vjudge.net/problem/POJ-3233
//构造矩阵B如下: 
//[A A]
//[0 I] 
//计算n次方
//目前看来,矩阵初始化会麻烦些。
//在 B[i][j]=1;//此处写成B[i][j]=1;漏了if,误以为单位矩阵是全1,查了10分钟 花了些时间
//样例通过,提交AC。2018-9-22 22:28 
#include <stdio.h>
#include <string.h>
#define LL long long
LL n,k,m,B[100][100],c[100][100],F[100][100];
void mul(){
    LL i,j,p;
    memset(c,0,sizeof(c));
    for(i=1;i<=2*n;i++)
        for(j=1;j<=2*n;j++)
            for(p=1;p<=2*n;p++)
                c[i][j]=(c[i][j]+B[i][p]*F[p][j])%m;
    memcpy(F,c,sizeof(c));
}
void mulself(){
    LL i,j,p;
    memset(c,0,sizeof(c));
    for(i=1;i<=2*n;i++)
        for(j=1;j<=2*n;j++)
            for(p=1;p<=2*n;p++)
                c[i][j]=(c[i][j]+B[i][p]*B[p][j])%m;
    memcpy(B,c,sizeof(c));
}
void quickPower(){
    LL i,j;
    while(k){
        if(k&1)mul();
        mulself();
        k>>=1;
    }
}
int main(){
    LL i,j,a;
    memset(B,0,sizeof(B));
    memset(F,0,sizeof(F));
    scanf("%lld%lld%lld",&n,&k,&m);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++){
            scanf("%lld",&a);
            B[i][j+n]=B[i][j]=a;
        }
    for(i=n+1;i<=2*n;i++)
        for(j=n+1;j<=2*n;j++)
            if(i==j) 
                B[i][j]=1;//此处写成B[i][j]=1;漏了if,误以为单位矩阵是全1,查了10分钟 
    for(i=1;i<=2*n;i++)
        for(j=1;j<=2*n;j++)
            if(i==j)F[i][j]=1;//单位矩阵
    quickPower();
    for(i=1;i<=n;i++){
        for(j=n+1;j<=2*n;j++)
            printf("%lld ",F[i][j]);
        printf("\n");
    }
    return 0;

//BZOJ4547 Hdu5171 小奇的集合
//GTY's birthday gift HDU - 5171
//在线测评地址https://vjudge.net/problem/HDU-5171
//基本思路,排序+矩阵乘法。 
//决定还是要学习C++中sort用法。
//样例数据模拟如下
//6 3 2
//9 6 3 2
//15 9 6 3 2  和即为 35
//[1,1,1]
//[0,1,1]*[ans,a[1],a[2]]
//[0,1,0] 
//样例通过,提交Wrong Answer 
//修改 ans=(ans+a[i])%mod;//此处写成ans+=a[i],造成Wrong Answer  提交,Wrong Answer
//多次排查程序无果,翻阅网络中的代码,再反复读题,发现“Multi test cases (about 3)”
//有多组测试样例,而本人的代码只有一组样例,马上修改。while(scanf("%lld%lld",&n,&k)!=EOF){//一开始,没有写成循环的形式
//提交,Wrong Answer. 
//翻看网络中的代码,发现问题出在ans初始化上。 //此处写成 LL i,ans=0; LL i,ans=0;//移到循环内。
//提交,AC。总结,测试时,同一个测试文件中一定要有多组数据,初始化问题就容易看出。2018-9-23 22:49 
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define mod 10000007
using namespace std;
LL a[100100],n,k,g[4],c[4][4];
int cmp(LL a,LL b){
    return a>b;//降序排列 

void mulself(LL A[4][4]){
    LL i,j,p;
    memset(c,0,sizeof(c));
    for(i=1;i<=3;i++)
        for(j=1;j<=3;j++)
            for(p=1;p<=3;p++)
                c[i][j]=(c[i][j]+A[i][p]*A[p][j])%mod;
    memcpy(A,c,sizeof(c));
}
void mul(LL A[4][4],LL B[4][4]){
    LL i,j,p;
    memset(c,0,sizeof(c));
    for(i=1;i<=3;i++)
        for(j=1;j<=3;j++)
            for(p=1;p<=3;p++)
                c[i][j]=(c[i][j]+A[i][p]*B[p][j])%mod;
    memcpy(B,c,sizeof(c));
}
void mulf(LL B[4][4],LL f[4]){
    LL i,j;
    memset(g,0,sizeof(g));
    for(i=1;i<=3;i++)
        for(j=1;j<=3;j++)
            g[i]=(g[i]+B[i][j]*f[j])%mod;
    memcpy(f,g,sizeof(g));
}
void quickPower(LL A[4][4],LL B[4][4]){
    while(k){
        if(k&1)mul(A,B);
        mulself(A);
        k>>=1;
    }
}
int main(){
    //此处写成 LL i,ans=0;
    while(scanf("%lld%lld",&n,&k)!=EOF){//一开始,没有写成循环的形式 
        LL i,ans=0;//移到循环内。 
        LL A[4][4]={{0,0,0,0},{0,1,1,1},{0,0,1,1},{0,0,1,0}};
        LL B[4][4]={{0,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
        LL f[4];
        for(i=1;i<=n;i++)scanf("%lld",&a[i]);
        sort(a+1,a+1+n,cmp);//此处写成 sort(a+1,a+n)
        for(i=1;i<=n;i++)ans=(ans+a[i])%mod;//此处写成ans+=a[i],造成Wrong Answer 
        f[0]=0,f[1]=ans,f[2]=a[1],f[3]=a[2];
        quickPower(A,B);
        mulf(B,f);
        printf("%lld\n",f[1]);
    }
    return 0;
}
//P2044 [NOI2012]随机数生成器
//在线测评地址https://www.luogu.org/problemnew/show/P2044
//构造矩阵如下
//[a,1]
//[0,1]*[x[n],c]
//样例没通过,查了半天,发现2阶矩阵,写成了3阶矩阵 for(i=1;i<=2;i++)//此处写成 for(i=1;i<=3;i++)
// //memcpy(f,G,sizeof(G));//此句竟然没有作用,无奈采用后面一句 
//因为上面这个问题,整整查了70分钟,编译器出现的问题。2018-9-24 11:13
//提交60分,测试点2,8,9,10 WA.2018-9-24 11:41
//看了数据,n,m,a,c,X[0]<=10^18,g<=10^8考虑,一不小心,long long 就要溢出,如何解决。
//以下为60分代码。 
//考虑 快速乘,详见https://blog.csdn.net/anxdada/article/details/76855632
//20*14=20*2^3+20*2^2+20*2^1+20*2^0
//20*14=20*0+40*1+80*1+160*1
//修改,提交AC。以下代码为100分代码。2018-9-24 16:15 
#include <stdio.h>
#include <string.h>
#define LL long long
LL m,a,c,X,n,g,C[3][3],G[3];
LL quickMul(LL a,LL b){
    LL ans=0;
    while(b){
        if(b&1)ans=(ans+a)%m;
        a=(a+a)%m;
        b>>=1;
    }
    return ans;//漏了该句 
}
void mulself(LL A[3][3]){
    LL i,j,k;
    memset(C,0,sizeof(C));
    for(i=1;i<=2;i++)//此处写成 for(i=1;i<=3;i++)
        for(j=1;j<=2;j++)
            for(k=1;k<=2;k++)
                C[i][j]=(C[i][j]+quickMul(A[i][k],A[k][j]))%m;
    memcpy(A,C,sizeof(C));
}
void mul(LL A[3][3],LL B[3][3]){
    LL i,j,k;
    memset(C,0,sizeof(C));
    for(i=1;i<=2;i++)
        for(j=1;j<=2;j++)
            for(k=1;k<=2;k++)
                C[i][j]=(C[i][j]+quickMul(A[i][k],B[k][j]))%m;
    memcpy(B,C,sizeof(C));
}
void mulf(LL f[3],LL B[3][3]){
    LL i,j;
    memset(G,0,sizeof(G));
    for(i=1;i<=2;i++)
        for(j=1;j<=2;j++)
            G[i]=(G[i]+quickMul(B[i][j],f[j]))%m;
    memcpy(f,G,sizeof(G));
}
void quickPower(LL n,LL A[3][3],LL B[3][3]){
    while(n){
        if(n&1)mul(A,B);
        mulself(A);
        n>>=1;
    }
}
int main(){
    LL A[3][3]={{0,0,0},{0,1,1},{0,0,1}};
    LL B[3][3]={{0,0,0},{0,1,0},{0,0,1}};
    LL f[3];
    scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&X,&n,&g);
    A[1][1]=a,f[0]=0,f[1]=X,f[2]=c;
    quickPower(n,A,B);
    mulf(f,B);
    printf("%lld\n",f[1]%g);
    return 0;
}
 

//P2044 [NOI2012]随机数生成器
//在线测评地址https://www.luogu.org/problemnew/show/P2044
//构造矩阵如下
//[a,1]
//[0,1]*[x[n],c]
//样例没通过,查了半天,发现2阶矩阵,写成了3阶矩阵 for(i=1;i<=2;i++)//此处写成 for(i=1;i<=3;i++)
// //memcpy(f,G,sizeof(G));//此句竟然没有作用,无奈采用后面一句 
//因为上面这个问题,整整查了70分钟,编译器出现的问题。2018-9-24 11:13
//提交60分,测试点2,8,9,10 WA.2018-9-24 11:41
//看了数据,n,m,a,c,X[0]<=10^18,g<=10^8考虑,一不小心,long long 就要溢出,如何解决。
//以下为60分代码。 
#include <stdio.h>
#include <string.h>
#define LL long long
LL m,a,c,X,n,g,C[3][3],G[3];
void mulself(LL A[3][3]){
    LL i,j,k;
    memset(C,0,sizeof(C));
    for(i=1;i<=2;i++)//此处写成 for(i=1;i<=3;i++)
        for(j=1;j<=2;j++)
            for(k=1;k<=2;k++)
                C[i][j]=(C[i][j]+A[i][k]%m*(A[k][j]%m))%m;
    memcpy(A,C,sizeof(C));
}
void mul(LL A[3][3],LL B[3][3]){
    LL i,j,k;
    memset(C,0,sizeof(C));
    for(i=1;i<=2;i++)
        for(j=1;j<=2;j++)
            for(k=1;k<=2;k++)
                C[i][j]=(C[i][j]+A[i][k]%m*(B[k][j])%m)%m;
    memcpy(B,C,sizeof(C));
}
void mulf(LL f[3],LL B[3][3]){
    LL i,j;
    memset(G,0,sizeof(G));
    for(i=1;i<=2;i++)
        for(j=1;j<=2;j++)
            G[i]=(G[i]+B[i][j]%m*(f[j]%m))%m;
    memcpy(f,G,sizeof(G));
}
void quickPower(LL n,LL A[3][3],LL B[3][3]){
    while(n){
        if(n&1)mul(A,B);
        mulself(A);
        n>>=1;
    }
}
int main(){
    LL A[3][3]={{0,0,0},{0,1,1},{0,0,1}};
    LL B[3][3]={{0,0,0},{0,1,0},{0,0,1}};
    LL f[3];
    scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&X,&n,&g);
    A[1][1]=a,f[0]=0,f[1]=X,f[2]=c;
    quickPower(n,A,B);
    mulf(f,B);
    printf("%lld\n",f[1]%g);
    return 0;
}
//快速乘 训练题 
//小余学数论
//在线测评地址http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=609
//采用快速乘
//样例通过,提交AC。
//1<=a,b,c<2^64 对2^64有顾虑,难道是64位系统。2018-9-24 16:46 
#include <stdio.h>
#define LL long long
LL quickMul(LL a,LL b,LL c){
    LL ans=0;
    while(b){
        if(b&1)ans=(ans+a)%c;
        a=(a+a)%c;
        b>>=1;
    }
    return ans;
}
int main(){
    LL a,b,c;
    while(scanf("%lld%lld%lld",&a,&b,&c)!=EOF){
        printf("%lld\n",quickMul(a,b,c));
    }
    return 0;


//Fibonacci Problem Again
//Fibonacci前n项和
//在线测评地址https://vjudge.net/problem/HIT-2060
//s(n)=f(0)+f(1)+...+f(n-1)+f(n)
//s(n)=s(n-1)+f(n)
//f(n)=f(n-1)+f(n-2)
//[1 1 0]
//[0 1 1]*[s(n-1),f(n),f(n-1)]=[s(n),f(n+1),f(n-1)];
//[0 1 0]
//想了想,为了程序编写更顺畅,决定重设矩阵,采用下面矩阵进行编码 
//[0 1 0]
//[1 1 0]*[f(n-1),f(n),s(n-1)]=[f(n),f(n-1)+f(n),s(n-1)+f(n)]=[f(n),f(n+1),s(n)]
//[0 1 1] 
//该题在处理a,b时,顺序颠倒了,找到这个问题,花了25分钟。 
//样例通过,专门测试了
//0 1
//2
//要提交时,发现Crawling failed 。2018-9-23 14:57
 
#include <stdio.h>
#include <string.h>
#define LL long long
#define mod 1000000000
LL a,b,c[4][4],g[4];
void mulf(LL a[4][4],LL f[4]){
    LL i,j;
    memset(g,0,sizeof(g));
    for(i=1;i<=3;i++)
        for(j=1;j<=3;j++)
            g[i]=(g[i]+a[i][j]*f[j])%mod;
    memcpy(f,g,sizeof(g));
}
void mul(LL a[4][4],LL b[4][4]){
    LL i,j,k;
    memset(c,0,sizeof(c));
    for(i=1;i<=3;i++)
        for(j=1;j<=3;j++)
            for(k=1;k<=3;k++)
                c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
    memcpy(b,c,sizeof(c));
}
void mulself(LL a[4][4]){
    LL i,j,k;
    memset(c,0,sizeof(c));
    for(i=1;i<=3;i++)
        for(j=1;j<=3;j++)
            for(k=1;k<=3;k++)
                c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
    memcpy(a,c,sizeof(c));
}
void quickPower(LL a[4][4],LL b[4][4],LL n){
    while(n){
        if(n&1)mul(a,b);
        mulself(a);
        n>>=1;
    }
}
int main(){
    LL i,j; 
    while(1){
        scanf("%lld%lld",&a,&b);
        if(a==b&&a==0)break;
        LL A1[4][4]={{0,0,0,0},{0,0,1,0},{0,1,1,0},{0,0,1,1}},f1[4]={0,1,1,1};//f[4] {0,f(1),f(2),s(1)}//此处写成f1[4]={0,1,1,1}//此处写成A1[4][4]={{0,0,1,0},{0,1,1,0},{0,0,1,1},{0,0,0,0}}//此处写成f1[4]={1,1,1,0}//f[4] {0,f(0),f(1),s(0)};
        LL B1[4][4]={{0,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};//此处写成 B1[4][4]={{0,1,0,0},{0,0,1,0},{0,0,0,1},{0,0,0,0}}
        if(a==0)f1[3]=0;
        else{
            quickPower(A1,B1,a-1);//此处写成 quickPower(A1,B1,b-1);
            if(a-1>=1)mulf(B1,f1);//此处写成if(b-1>=1)//漏了if(b-1>=1)//漏了此句
        }
        LL A2[4][4]={{0,0,0,0},{0,0,1,0},{0,1,1,0},{0,0,1,1}},f2[4]={0,1,1,1};
        LL B2[4][4]={{0,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
        quickPower(A2,B2,b);
        if(b==0)f2[3]=1;
        else
            if(b>=1)mulf(B2,f2);//漏了if(a>=1)
        printf("%lld\n",(f2[3]-f1[3]+mod)%mod);//此处写成 printf("%lld\n",f2[3]-f1[3]+mod%mod);
    }
    
    return 0;

//Problem of Precision HDU - 2256
//在线测评地址https://vjudge.net/problem/HDU-2256

//构造矩阵如下:
//[0 1]
//[-1 10]*[f[n-2],f[n-1]]=[f[n-1],f[n]]
//测试同一样例的多组数据时,出现问题,仔细想了想,应该是每处理一组数据时,就应初始化一次,这个没注意到。
//马上修改,样例通过,提交AC,提交前,心怀忐忑,若是不通过,真想不出什么好办法。2018-9-25 
#include <stdio.h>
#include <string.h>
#define mod 1024
#define LL long long
void mulf(LL B[3][3],LL f[3]){
    LL i,j,k,g[3];
    memset(g,0,sizeof(g));
    for(i=1;i<=2;i++)
        for(j=1;j<=2;j++)
            g[i]=(g[i]+B[i][j]*f[j])%mod;
    memcpy(f,g,sizeof(g));
}
void mul(LL A[3][3],LL B[3][3]){
    LL i,j,k,c[3][3];
    memset(c,0,sizeof(c));
    for(i=1;i<=2;i++)
        for(j=1;j<=2;j++)
            for(k=1;k<=2;k++)
                c[i][j]=(c[i][j]+A[i][k]*B[k][j])%mod;
    memcpy(B,c,sizeof(c));
}
void mulself(LL A[3][3]){
    LL i,j,k,c[3][3];
    memset(c,0,sizeof(c));
    for(i=1;i<=2;i++)
        for(j=1;j<=2;j++)
            for(k=1;k<=2;k++)
                c[i][j]=(c[i][j]+A[i][k]*A[k][j])%mod;
    memcpy(A,c,sizeof(c));
}
void quickPower(LL A[3][3],LL B[3][3],LL n){
    while(n){
        if(n&1)mul(A,B);
        mulself(A);
        n>>=1;
    }
}
int main(){
    LL T,n;
    scanf("%lld",&T);
    while(T--){
        LL A[3][3]={{0,0,0},{0,0,1},{0,-1,10}},B[3][3]={{0,0,0},{0,1,0},{0,0,1}};//写在while循环之外了 
        LL f[3]={0,2,10};
        scanf("%lld",&n);
        quickPower(A,B,n-1);
        mulf(B,f);
        printf("%lld\n",(f[2]+mod-1)%mod);//+mod原因是 处理 负数 
    }
    return 0;

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值