快速幂和矩阵快速幂

  1. 快速幂

 1.1 递归实现

int quickMul(int a, int n)
{
	int ans;
	if( n==0)
		ans = 1;
	else
	{
		ans = quickMul(a*a, n/2);
		if(n%2==1)
			ans *= a;
	}
	return ans;
}

1.2 循环实现

int quickMul(int a, int n)
{
	int ans = 1;
	while(n)
	{
		if(n%2)
			ans = ans*a;
		a = a*a;
		n = n/2;
	}
	return ans;
}

    2. 矩阵快速幂

2.1 模板代码

struct matrix  //定义一个结构体,方便传递值
{
    int m[MAXN][MAXN];
};
int k, m;

matrix matrixMul(matrix a, matrix b)
{
    matrix ans;
    for (int i = 0; i < N; i++) 
    {
        for (int j = 0; j < N; j++) 
        {
            ans.m[i][j] = 0;
            for (int k = 0; k < N; k++) 
            {
                ans.m[i][j] += (a.m[i][k] % m * b.m[k][j] % m) % m;
                ans.m[i][j] %= m;
            }
        }
    }
    return ans;
}

matrix quickMul(matrix ori, int k)
{
    matrix ans;
    //这里要初始化为单位矩阵,类比普通快速幂这里初始化为1
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < N; j++)
        {
            if(i == j)
                ans.m[i][j] = 1;
            else
                ans.m[i][j] = 0;
        }
    }

    while(k > 0)
    {
        if(k % 2 == 1)
            ans = matrixMul(ans, ori);
        ori = matrixMul(ori, ori);
        k /= 2;
    }
    return ans;
}

 2.2 Example

2.2.1 G Tr A

#include <bits/stdc++.h>
using namespace std; 

#define MAXN 15
#define MOD 9973
struct matrix
{
    int m[MAXN][MAXN];
};
int n, k;

matrix matrixMul(matrix a, matrix b)
{
	matrix ans;
	for (int i = 0; i < n; i++) 
	{
        for (int j = 0; j < n; j++) 
		{
        	ans.m[i][j] = 0;
            for (int k = 0; k < n; k++) 
			{
                ans.m[i][j] += (a.m[i][k] * b.m[k][j]) % MOD;
                ans.m[i][j] %= MOD;
            }
        }
    }
    return ans;
}

matrix quickMul(matrix a, int k)
{
	matrix ans;
	for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            if(i == j)
                ans.m[i][j] = 1;
            else
                ans.m[i][j] = 0;
        }
    }
    
	while(k != 0)
    {
        if(k % 2 == 1)
            ans = matrixMul(a, ans);
        a = matrixMul(a, a);
        k /= 2;
    }
    return ans;
}

int main()
{
	int num;
	scanf("%d", &num);
	while(num--)
	{
        //构建A矩阵
		matrix a;
		scanf("%d %d", &n, &k);
		for(int i=0; i<n; i++)
		{
			for(int j=0; j<n; j++)
				scanf("%d", &a.m[i][j]);
		}
		//矩阵快速幂运算
		matrix tmp = quickMul(a, k);
        int trace = 0;
        for(int i = 0; i < n; i++)
            trace += tmp.m[i][i] % MOD;

        trace %= MOD;    
        printf("%d\n", trace);
	}
}

2.2.2 H A Simple Math Problem 

 

#include <bits/stdc++.h>
using namespace std; 

#define N 10
#define MAXN 15
struct matrix
{
    int m[MAXN][MAXN];
};
int k, m;

matrix matrixMul(matrix a, matrix b)
{
    matrix ans;
    for (int i = 0; i < N; i++) 
    {
        for (int j = 0; j < N; j++) 
        {
            ans.m[i][j] = 0;
            for (int k = 0; k < N; k++) 
            {
                ans.m[i][j] += (a.m[i][k] % m * b.m[k][j] % m) % m;
                ans.m[i][j] %= m;
            }
        }
    }
    return ans;
}

matrix quickMul(matrix ori, int k)
{
    matrix ans;
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < N; j++)
        {
            if(i == j)
                ans.m[i][j] = 1;
            else
                ans.m[i][j] = 0;
        }
    }

    while(k > 0)
    {
        if(k % 2 == 1)
            ans = matrixMul(ans, ori);
        ori = matrixMul(ori, ori);
        k /= 2;
    }
    return ans;
}

int main()
{
    while(scanf("%d %d", &k, &m) == 2)
    {
        matrix ori;
        for(int i=0; i<N; i++)
            for(int j=0; j<N; j++)
                ori.m[i][j] = 0;
        for(int i=0; i<N; i++)
        {
            scanf("%d", &ori.m[0][i]);
            ori.m[i+1][i] = 1;
        }
        matrix tmp = quickMul(ori, k-9);
        int finNum = 0;
        for(int i=0; i<N; i++)
            finNum += tmp.m[0][i]*(9-i);
        printf("%d\n", finNum % m);
    }
    return 0;
}

2.2.3 J Count

 

#include <bits/stdc++.h>
using namespace std; 

#define N 6
#define MAXN 10
#define mod 123456789

struct Matrix {
    int m[MAXN][MAXN];
};

Matrix matrixMul(Matrix a, Matrix b) {
    Matrix ans;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            ans.m[i][j] = 0;
            for (int k = 0; k < N; k++) {
                ans.m[i][j] += (1LL * a.m[i][k] * b.m[k][j]) % mod;
                ans.m[i][j] %= mod;
            }
        }
    }
    return ans;
}

Matrix quickMul(Matrix ori, long long k) {
    Matrix ans;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (i == j) {
                ans.m[i][j] = 1;
            } else {
                ans.m[i][j] = 0;
            }
        }
    }

    while (k > 0) {
        if (k % 2 == 1) {
            ans = matrixMul(ans, ori);
        }
        ori = matrixMul(ori, ori);
        k /= 2;
    }
    return ans;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        long long n;
        cin >> n;
        Matrix ans;
        Matrix ori = {
            {
                {1, 2, 1, 3, 3, 1},
                {1, 0, 0, 0, 0, 0},
                {0, 0, 1, 3, 3, 1},
                {0, 0, 0, 1, 2, 1},
                {0, 0, 0, 0, 1, 1},
                {0, 0, 0, 0, 0, 1}
            }
        };
        memset(ans.m, 0, sizeof(ans.m));
        ans.m[0][0] = 2;
        ans.m[1][0] = 1;
        ans.m[2][0] = 8;
        ans.m[3][0] = 4;
        ans.m[4][0] = 2;
        ans.m[5][0] = 1;
        Matrix tmp = quickMul(ori, n - 2);
        tmp = matrixMul(tmp, ans);
        printf("%d\n", tmp.m[0][0]%mod);
    }
    return 0;
}

2.2.4 K Sum of Tribonacci Numbers

 

#include <bits/stdc++.h>
using namespace std; 

#define N 4
#define MAXN 5
#define mod 1000000007

struct Matrix {
    int m[MAXN][MAXN];
};

Matrix ans;
Matrix ori = {
    {
        {1, 1, 1, 1},
        {0, 1, 1, 1},
        {0, 1, 0, 0},
        {0, 0, 1, 0}
    }
};

Matrix matrixMul(Matrix a, Matrix b) {
    Matrix ans;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            ans.m[i][j] = 0;
            for (int k = 0; k < N; k++) {
                ans.m[i][j] += (1LL * a.m[i][k] * b.m[k][j]) % mod;
                ans.m[i][j] %= mod;
            }
        }
    }
    return ans;
}

Matrix quickMul(Matrix ori, long long k) {
    Matrix ans;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (i == j) {
                ans.m[i][j] = 1;
            } else {
                ans.m[i][j] = 0;
            }
        }
    }

    while (k > 0) {
        if (k % 2 == 1) {
            ans = matrixMul(ans, ori);
        }
        ori = matrixMul(ori, ori);
        k /= 2;
    }
    return ans;
}

int sum(int a)
{
	if(a<=2)
       	return a + 1;
    else
    {
        Matrix tmp1 = quickMul(ori, a - 2);
        tmp1 = matrixMul(tmp1, ans);
        return tmp1.m[0][0];
	}
}

int main() {
    int a, b;
    while (scanf("%d %d", &a, &b) == 2) {
        memset(ans.m, 0, sizeof(ans.m));
        ans.m[0][0] = 3;
        ans.m[1][0] = 1;
        ans.m[2][0] = 1;
        ans.m[3][0] = 1;
        cout << (sum(b)-sum(a-1)+mod) % mod << endl;  //需要+mod防止出现负数
    }
    return 0;
}

2.2.5 L Another kind of Fibonacci

 

#include <bits/stdc++.h>
using namespace std; 

#define N 4
#define MAXN 10
#define mod 10007

struct Matrix {
    int m[MAXN][MAXN];
};

Matrix matrixMul(Matrix a, Matrix b) {
    Matrix ans;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            ans.m[i][j] = 0;
            for (int k = 0; k < N; k++) {
                ans.m[i][j] += (1LL * a.m[i][k] * b.m[k][j]) % mod;
                ans.m[i][j] %= mod;
            }
        }
    }
    return ans;
}

Matrix quickMul(Matrix ori, long long k) {
    Matrix ans;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (i == j) {
                ans.m[i][j] = 1;
            } else {
                ans.m[i][j] = 0;
            }
        }
    }

    while (k > 0) {
        if (k % 2 == 1) {
            ans = matrixMul(ans, ori);
        }
        ori = matrixMul(ori, ori);
        k /= 2;
    }
    return ans;
}

int main() {
    int n, x, y;
    while (scanf("%d %d %d", &n, &x, &y) == 3) {
    	x %= mod;
		y %= mod;
        Matrix ans;
        Matrix ori = {
            {
                {1, x*x, 2*x*y, y*y},
                {0, x*x, 2*x*y, y*y},
                {0, x, y, 0},
                {0, 1, 0, 0}
            }
        };
        memset(ans.m, 0, sizeof(ans.m));
        ans.m[0][0] = 2;
        ans.m[1][0] = 1;
        ans.m[2][0] = 1;
        ans.m[3][0] = 1;
        Matrix tmp = quickMul(ori, n - 1);
        tmp = matrixMul(tmp, ans);
        cout << tmp.m[0][0] % mod << endl;
    }
    return 0;
}

2.2.6 M Kiki & Little Kiki 2

#include <bits/stdc++.h>
using namespace std; 

#define MAXN 110
#define mod 2

struct Matrix {
    int m[MAXN][MAXN];
};
int l;

Matrix matrixMul(Matrix a, Matrix b) {
    Matrix ans;
    for (int i = 0; i < l; i++) {
        for (int j = 0; j < l; j++) {
            ans.m[i][j] = 0;
            for (int k = 0; k < l; k++) {
                ans.m[i][j] += (1LL * a.m[i][k] * b.m[k][j]) % mod;
                ans.m[i][j] %= mod;
            }
        }
    }
    return ans;
}

Matrix quickMul(Matrix ori, long long k) {
    Matrix ans;
    for (int i = 0; i < l; i++) {
        for (int j = 0; j < l; j++) {
            if (i == j) {
                ans.m[i][j] = 1;
            } else {
                ans.m[i][j] = 0;
            }
        }
    }

    while (k > 0) {
        if (k % 2 == 1) {
            ans = matrixMul(ans, ori);
        }
        ori = matrixMul(ori, ori);
        k /= 2;
    }
    return ans;
}

int main() {
    long long n;
    while (cin >> n) {
        Matrix ori, ans;
        memset(ans.m, 0, sizeof(ans.m));
        string T;
        cin >> T;
        l = T.length();
        for(int i=0; i<l; i++)
        	ans.m[i][0] = T[i]-48;
        memset(ori.m, 0, sizeof(ori.m));
        for(int i=1; i<l; i++)
        	ori.m[i][i] = ori.m[i][i-1] = 1;
        ori.m[0][0] = ori.m[0][l-1] = 1;
        Matrix tmp = quickMul(ori, n);
        tmp = matrixMul(tmp, ans);
        for(int i=0; i<l; i++)
        	printf("%d", tmp.m[i][0]);
        printf("\n");
    }
    return 0;
}

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值