快速幂(二进制,十进制)

3 篇文章 0 订阅
2 篇文章 0 订阅

矩阵快速幂:

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
typedef long long LL;

const int maxn = 3*1e6+5;
struct Matrix{
	long long an[2][2];
};

LL a, b, x0, x1;
char n[maxn];
LL mod;

Matrix Multi(Matrix A, Matrix B){
	Matrix C;
	C.an[0][0] = C.an[0][1] = C.an[1][0] = C.an[1][1] = 0;

	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 2; j++)
			for(int k = 0; k < 2; k++)
				C.an[i][j] = (C.an[i][j] + A.an[i][k] * B.an[k][j]) % mod;

	return C;
}

//二进制快速幂
Matrix quick_mod2(Matrix A, long long n){
	Matrix B;
	B.an[0][0] = B.an[1][1] = 1;
	B.an[0][1] = B.an[1][0] = 0;
	while(n){
		if(n&1) B = Multi(B, A);
		A = Multi(A, A);
		n >>= 1;
	}
	return B;
}

//十进制快速幂
Matrix quick_mod10(Matrix A, char s[]){
    Matrix B, t = A;
    B.an[0][0] = B.an[1][1] = 1;
	B.an[0][1] = B.an[1][0] = 0;

	int len = strlen(s);
	len--;
	
	while(len >= 0){
	    LL num = s[len] - '0';
		Matrix cur = t;
		for(int i = 1; i <= num; i++) 
            B = Multi(B, t);
		for(int i = 1; i < 10; i++)
            cur = Multi(cur, t);
		t = cur;
		len--;
	}
	return B;
}

int main()
{
        scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
        scanf("%s", n);
        scanf("%lld", &mod);

        int len = strlen(n);

		Matrix A, ans;
		A.an[0][0] = a; A.an[0][1] = b;
		A.an[1][0] = 1; A.an[1][1] = 0;


		ans = quick_mod10(A, n);
	//	printf("%lld %lld\n", ans.an[0][0], ans.an[0][1]);
		printf("%lld\n", (ans.an[1][0]*x1 + ans.an[1][1]*x0) % mod);
}

题目:牛客多校第五场 https://ac.nowcoder.com/acm/contest/885/B

 

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
typedef long long LL;

const int maxn = 3*1e6+5;
struct Matrix{
	long long an[2][2];
};

LL a, b, x0, x1;
char n[maxn];
LL mod;

Matrix Multi(Matrix A, Matrix B){
	Matrix C;
	C.an[0][0] = C.an[0][1] = C.an[1][0] = C.an[1][1] = 0;

	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 2; j++)
			for(int k = 0; k < 2; k++)
				C.an[i][j] = (C.an[i][j] + A.an[i][k] * B.an[k][j]) % mod;

	return C;
}

Matrix quick_mod(Matrix A, long long n){
	Matrix B;
	B.an[0][0] = B.an[1][1] = 1;
	B.an[0][1] = B.an[1][0] = 0;
	while(n){
		if(n&1) B = Multi(B, A);
		A = Multi(A, A);
		n >>= 1;
	}
	return B;
}

//十进制快速幂
Matrix quick_mod10(Matrix A, char s[]){
    Matrix B, t = A;
    B.an[0][0] = B.an[1][1] = 1;
	B.an[0][1] = B.an[1][0] = 0;

	int len = strlen(s);
	len--;
// 	LL num = s[len] - '0' - 1;
// 	Matrix cur = t;
// 	for(int i = 1; i <= num; i++)
// 	    B = Multi(B, t);
// 	for(int i = 1; i < 10; i++)
// 	    cur = Multi(cur, t);
// 	t = cur;
// 	len--;
	
	while(len >= 0){
	    LL num = s[len] - '0';
		Matrix cur = t;
		for(int i = 1; i <= num; i++) 
            B = Multi(B, t);
		for(int i = 1; i < 10; i++)
            cur = Multi(cur, t);
		t = cur;
		len--;
	}
	return B;
}

int main()
{
        scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
        scanf("%s", n);
        scanf("%lld", &mod);

        int len = strlen(n);

		Matrix A, ans;
		A.an[0][0] = a; A.an[0][1] = b;
		A.an[1][0] = 1; A.an[1][1] = 0;

	   // int k = 0;
    //     for(int i = len-1;i >= 0;--i)
    //     {
    //         if(n[i] != '0'){
    //             k = i;
    //             break;
    //         }
    //     }
    //     n[k] -= 1;
    //     for(int i = len-1;i > k;--i)
    //         n[i] = '9';

		ans = quick_mod10(A, n);
	//	printf("%lld %lld\n", ans.an[0][0], ans.an[0][1]);
		printf("%lld\n", (ans.an[1][0]*x1 + ans.an[1][1]*x0) % mod);
}

 

 

普通二进制快速幂、十进制快速幂

//二进制快速幂
LL quick_mod2(LL x, LL n, LL mod)      //x ^ n
{
    LL res = 1;
    while(n){
        if(n & 1) res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
}

//十进制快速幂
LL quick_mod10(LL x, char s[], LL mod){
    LL res = 1, t = x;
    int len = strlen(s); len--;

    while(len >= 0){
        int num = s[i] - '0', cur = t;
        
        for(int i = 1; i <= num; i++)
             ans = ans * t % mod;
        for(int i = 1; i < 10; i++)
            cur = cur * t % mod;
        
        t = cur;
        len--;
    }
    
    return res;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值