E. Exponentiation,矩阵连乘,思维,数学

Problem - E - Codeforces

                                E. Exponentiation

time limit per test

3 seconds

memory limit per test

1024 megabytes

input

standard input

output

standard output

Exponentiation is a mathematical operation that involves raising a base number to a certain exponent to obtain a result. In the expression an, where a is the base and n is the exponent, it means multiplying a by itself n times. The result of this operation is called the exponentiation of a to the n-th power. For examples, 23=2×2×2=8and 52=5×5=25. In these examples, 2 is the base, 3 is the exponent in the first case, and 5 is the base, and 2 is the exponent in the second case. Exponentiation is a fundamental operation in mathematics and is commonly used in various contexts, such as solving equations, and cryptography.

In many cryptographic algorithms, particularly those based on number theory like RSA (Rivest-Shamir-Adleman) and Diffie-Hellman, modular exponentiation is a fundamental operation. Modular exponentiation involves raising a base to an exponent modulo a modulus. This operation is computationally intensive but relatively easy to perform, even for very large numbers.

Let x+1x=α where α is a positive integer. Please write a program to compute xβ+1xβ mod m for given positive integers β and m.

Input

The input has only one line, and it contains three space-separated positive integers α, β and m. α, β and m are positive integers less than 2^64.

Output

Outout xβ+1xβ mod m. You may assume xβ+1xβ is an integer. If there are multiple solutions, you may output any of them in the range from 0 to m−1.

Examples

input

Copy

1 2 3

output

Copy

2

input

Copy

5 4 321

output

Copy

206

input

Copy

3 3 333

output

Copy

18

input

Copy

8 8 888

output

Copy

626

Note

x can be a complex number. For example, x is either 1+3√i2 or 1−3√i2 if α=1. However, xβ+1xβ is always an integer in this problem.

题解:

本题需要推出递推公式 f[n]=f[n-1]*a-f[n-2];
又因为本题的n很大,所以要用到矩阵快速幂;
同时long long 的最大范围为2^63,即使是unsigned long long 最大也仅有2^64-1
所以需要用__uint128_t
而且不是所有的系统都能运行,所以用python写最好,这里就提供一个思路,python代码就不写了

会爆掉的代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef  long long LL;

LL A, B, m;
typedef struct matrx {
	LL m[2][2];
}matrix;
matrix p = {
	1,-1,
	1,0
};
matrix I = {
	1,0,
	0,1
};

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

matrix matrixpow(LL x) {
	matrix ret = I, t = p;
	while (x) {
		if (x & 1) {
			ret=muiltmatrix(ret, t);
		}
		x >>= 1;
		t=muiltmatrix(t, t);
	}
	return ret;
}

int main() {
	scanf("%lld%lld%lld", & A, &B, &m);
	p.m[0][0] = A;
	LL f1 = A;
	LL f2 = ((A % m) * (A % m) - 2 + m) % m;
	if (B == 1) {
		cout << A << endl;
	}
	else if (B == 2) {
		cout << f2 << endl;
	}
	else {
		matrix ret = matrixpow(B - 2);
		LL ans = ((ret.m[0][0] * f2) % m + (ret.m[0][1] * f1) % m + m) % m;
		cout << ans << endl;
	}
	return 0;
}

出题人的代码

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

using ull = unsigned long long;
using ulll = __uint128_t;
ull a, b, m;

struct matrix {
    ull A[2][2];
    matrix() { memset(A, 0, sizeof A); }
    matrix operator*(const matrix& rhs) const {
        matrix ret;
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                for (int k = 0; k < 2; k++) {
                    ret.A[i][j] =
                        ((ulll)ret.A[i][j] + (ulll)A[i][k] * rhs.A[k][j] % m) % m;
                }
        return ret;
    }
};

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> a >> b >> m;

    matrix M, ans;
    M.A[0][0] = a, M.A[0][1] = m - 1;
    M.A[1][0] = 1, M.A[1][1] = 0;
    ans.A[0][0] = 1, ans.A[0][1] = 0;
    ans.A[1][0] = 0, ans.A[1][1] = 1;
    b--;
    while (b) {
        if (b & 1)
            ans = ans * M;
        M = M * M;
        b >>= 1;
    }
    cout << (ull)(((ulll)ans.A[0][0] * a % m + (ulll)ans.A[0][1] * 2 % m) % m)<< '\n';
}

posted @   Landnig_on_Mars  阅读(17)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示