快速幂应用

矩阵快速幂自乘

typedef vector< int > vec;
typedef vector< vector< int > > mat;

mat multi( const mat& A, const mat& B ){

    mat C( A.size(), vec ( B[0].size() ) );

    for( int i = 0; i < A.size(); ++i ){
        for( int k = 0; k < B.size(); ++k ){
            for( int j = 0; j < B[0].size(); ++j ){
                C[i][j] = ( C[i][j] + A[i][k] * B[k][j] ) % MOD;
            }
        }
    }

    return C;

}

mat quick_pow( mat& A, LL n ){

    int row = A.size();
    int col = A[0].size();
    mat B( row, vec( col ) );

    for( int i = 0; i < row; ++i ){
        B[i][i] = 1;
    }

    while( n > 0 ){

        if( n & 1 )
            B = multi( B, A );

        A = multi( A, A );
        n >>= 1;

    }

    return B;

}

Google Code Jam -- Number( 2008 Round C )

求 ( 3 + 5 ^ 0.5 ) ^ N ( 1 <= N <= 10 ^ 9 ) 整数部分的最后三位,不足三位数的话首部填零。

( 3 + 5 ^ 0.5 ) ^ N 都可以变形为 ( A + B * ( 5 ^ 0.5 ) ) 的结构

( 3 + 5 ^ 0.5 ) ^ ( N + 1 ) = ( 3 + 5 ^ 0.5 ) * ( 3 + 5 ^ 0.5 ) ^ N

                            = ( 3 + 5 ^ 0.5 ) * ( A + B * ( 5 ^ 0.5 ) )

                            = ( A‘ + B‘ * ( 5 ^ 0.5 ) )

A‘ = 3 * A + 5 * B

B‘ = A + 3 * B

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

#define MOD 1000
#define LL long long

typedef vector< int > vec;
typedef vector< vector< int > > mat;

mat multi( const mat& A, const mat& B ){

    mat C( A.size(), vec ( B[0].size() ) );

    for( int i = 0; i < A.size(); ++i ){
        for( int k = 0; k < B.size(); ++k ){
            for( int j = 0; j < B[0].size(); ++j ){
                C[i][j] = ( C[i][j] + A[i][k] * B[k][j] ) % MOD;
            }
        }
    }

    return C;

}

mat quick_pow( mat& A, LL n ){

    int row = A.size();
    int col = A[0].size();
    mat B( row, vec( col ) );

    for( int i = 0; i < row; ++i ){
        B[i][i] = 1;
    }

    while( n > 0 ){

        if( n & 1 )
            B = multi( B, A );

        A = multi( A, A );
        n >>= 1;

    }

    return B;

}

int main(){

    LL n;
    mat A( 2, vec( 2, 0 ) );

    A[0][0] = 3; A[0][1] = 5;
    A[1][0] = 1; A[1][1] = 3;

    cin >> n;

    A = quick_pow( A, n );

    printf( "%03d\n", ( A[0][0] * 2 + MOD - 1 ) % MOD );

    return 0;
}
POJ 3070 斐波那契

求解第 N( 1 <= N <= 10 ^ 9 ) 个斐波那契数

| F( n + 2 ) |            | 1     1  |       |  F( n + 1 ) |

|            |     =      |          |   *   |             |

| F( n + 1 ) |            | 1     0  |       |    F( n )   |

|  F( n + 1 )  |                 |   F( 1 )   |

|              |    =   A ^ n *  |            |

|    F( n )    |                 |   F( 0 )   |

#include <iostream>
#include <vector>
using namespace std;

#define MOD 10007
#define LL long long

typedef vector< int > vec;
typedef vector< vector< int > > mat;

mat multi( const mat& A, const mat& B ){

    mat C( A.size(), vec ( B[0].size() ) );

    for( int i = 0; i < A.size(); ++i ){
        for( int k = 0; k < B.size(); ++k ){
            for( int j = 0; j < B[0].size(); ++j ){
                C[i][j] = ( C[i][j] + A[i][k] * B[k][j] ) % MOD;
            }
        }
    }

    return C;

}

mat quick_pow( mat& A, LL n ){

    int row = A.size();
    int col = A[0].size();
    mat B( row, vec( col ) );

    for( int i = 0; i < row; ++i ){
        B[i][i] = 1;
    }

    while( n > 0 ){

        if( n & 1 )
            B = multi( B, A );

        A = multi( A, A );
        n >>= 1;

    }

    return B;

}

int main(){

    int test;

    cin >> test;

    while( test-- ){

        LL n;
        mat A( 3, vec ( 3 ) );

        A[0][0] = 2; A[0][1] = 1; A[0][2] = 0;
        A[1][0] = 2; A[1][1] = 2; A[1][2] = 2;
        A[2][0] = 0; A[2][1] = 1; A[2][2] = 2;

        cin >> n;

        A = quick_pow( A, n );

        cout << A[0][0] << endl;

    }
    return 0;
}
POJ 3734 Blocks

一行 N 个方块,每块只能用用 A, B, C, D 四种之一颜色涂满,求含有偶数个颜色 A 和 偶数个颜色 B 的方块的涂色方案的个数。

递推:

涂到第 i 块的时后,A, B 都是偶数的方案个数为 X,一奇一偶方案个数为 Y,全为奇数方案个数为 Z

那么低 i + 1 的可能性:

X‘ = 2 * X + Y

Y‘ = 2 * X + 2 * Y + 2 * Z

Z‘ = Y + 2 * Z

#include <iostream>
#include <vector>
using namespace std;

#define MOD 10007
#define LL long long

typedef vector< int > vec;
typedef vector< vector< int > > mat;

mat multi( const mat& A, const mat& B ){

    mat C( A.size(), vec ( B[0].size() ) );

    for( int i = 0; i < A.size(); ++i ){
        for( int k = 0; k < B.size(); ++k ){
            for( int j = 0; j < B[0].size(); ++j ){
                C[i][j] = ( C[i][j] + A[i][k] * B[k][j] ) % MOD;
            }
        }
    }

    return C;

}

mat quick_pow( mat& A, LL n ){

    int row = A.size();
    int col = A[0].size();
    mat B( row, vec( col ) );

    for( int i = 0; i < row; ++i ){
        B[i][i] = 1;
    }

    while( n > 0 ){

        if( n & 1 )
            B = multi( B, A );

        A = multi( A, A );
        n >>= 1;

    }

    return B;

}

int main(){

    int test;

    cin >> test;

    while( test-- ){

        LL n;
        mat A( 3, vec ( 3 ) );

        A[0][0] = 2; A[0][1] = 1; A[0][2] = 0;
        A[1][0] = 2; A[1][1] = 2; A[1][2] = 2;
        A[2][0] = 0; A[2][1] = 1; A[2][2] = 2;

        cin >> n;

        A = quick_pow( A, n );

        cout << A[0][0] << endl;

    }
    return 0;
}
时间: 2024-08-02 19:19:03

快速幂应用的相关文章

矩阵快速幂刷题系列

来源自http://blog.csdn.net/chenguolinblog/article/details/10309423 hdu 1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5587    Accepted Submission(s): 4200 Problem Description A为一个方阵,则Tr

快速幂取模(POJ 1995)

http://poj.org/problem?id=1995 以这道题来分析一下快速幂取模 a^b%c(这就是著名的RSA公钥的加密方法),当a,b很大时,直接求解这个问题不太可能 利用公式a*b%c=((a%c)*b)%c 每一步都进行这种处理,这就解决了a^b可能太大存不下的问题,但这个算法的时间复杂度依然没有得到优化 由此可以用快速幂算法优化: http://www.cnblogs.com/qlky/p/5020402.html 再结合取模公式: (a + b) % p = (a % p

HDU 1757 A Simple Math Problem (矩阵快速幂)

[题目链接]:click here~~ [题目大意]: If x < 10 f(x) = x. If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 * f(x-10); 问f(k)%m的值. [思路]:矩阵快速幂,具体思路看代码吧,注意一些细节. 代码: #include<bits/stdc++.h> using namespace std; typedef long long LL; const

快速幂及快速幂取模

快速幂顾名思义,就是快速算某个数的多少次幂.其时间复杂度为 O(log?N), 与朴素的O(N)相比效率有了极大的提高.——bybaidu 快速幂可以用位运算这个强大的工具实现. 代码: 1 int pow(int a,int b) 2 { 3 int ans=1; 4 while(b!=0) 5 { 6 if(b&1) 7 ans*=a; 8 a*=a; 9 b>>=1; 10 } 11 return ans; 12 } 快速幂取模需要记住一个定理:积的取模等于取模积的取模:算法是蒙

Codeforces Round #291 (Div. 2) E - Darth Vader and Tree (DP+矩阵快速幂)

这题想了好长时间,果断没思路..于是搜了一下题解.一看题解上的"快速幂"这俩字,不对..这仨字..犹如醍醐灌顶啊...因为x的范围是10^9,所以当时想的时候果断把dp递推这一方法抛弃了.我怎么就没想到矩阵快速幂呢.......还是太弱了..sad..100*100*100*log(10^9)的复杂度刚刚好. 于是,想到了矩阵快速幂后,一切就变得简单了.就可以把距离<=x的所有距离的点数都通过DP推出来,然后一个快速幂就解决了. 首先DP递推式很容易想到.递推代码如下: for(

NYOJ127 星际之门(一)(最小生成数的个数+快速幂)

题目描述: http://acm.nyist.net/JudgeOnline/problem.php?pid=127 可以证明,修建N-1条虫洞就可以把这N个星系连结起来. 现在,问题来了,皇帝想知道有多少种修建方案可以把这N个星系用N-1条虫洞连结起来? 输入 第一行输入一个整数T,表示测试数据的组数(T<=100) 每组测试数据只有一行,该行只有一个整数N,表示有N个星系.(2<=N<=1000000) 输出 对于每组测试数据输出一个整数,表示满足题意的修建的方案的个数.输出结果可能

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st

HDU 4990 Reading comprehension(找规律+矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4990 Problem Description Read the program below carefully then answer the question. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include<iostream> #include

hdu 6198(矩阵快速幂)

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 119 暴力发现当4 12 33 88 232 和斐波那契数列对比  答案为 第2*k+3个数减1 直接用矩阵快速幂求的F[2*k+3]  然后减1 A=1,B=0; 然后矩阵快速幂2*k

矩阵快速幂 模板与简单讲解

模板 快速幂模板 1 void solve(matrix t,long long o) 2 { 3 matrix e; 4 5 memset(e.a,0,sizeof(e.a)); 6 7 for (int i = 0;i < d;i++) 8 e.a[i][i] = 1; 9 10 while (o) 11 { 12 if (o & 1) 13 { 14 e = mul(e,t); 15 } 16 17 o >>= 1; 18 19 t = mul(t,t); 20 } 21