1.基本原理
(a * b) % p = (a % p * b % p) % p
测试链接:http://acm.hdu.edu.cn/showproblem.php?pid=1021


#include <iostream> #include <stdio.h> using namespace std; int main(){ int n; while(scanf("%d",&n)!=EOF){ int f0=7,f1=11; int fn; for(int i=2;i<=n;i++){ fn=(f0+f1)%3; f0=f1%3; f1=fn%3; } if(n<=1){ cout<<"no"<<endl; } else{ if(fn%3==0) cout<<"yes"<<endl; else cout<<"no"<<endl; } } return 0; }
2.快速幂
原理:
比如 a^7=a^4*a^2*a^1=(a^2*a^2)*(a^1*a^1)*a^1。
简单来说,就是求过的 a^i 的值不再求一遍,拿来直接用。
板子:
//x^n % mod int quickPower(int x, int n, int mod) { int t = x, res = 1; while (n) { if (n & 1) res = ((res % mod) * (t % mod)) % mod; t = ((t % mod) * (t % mod)) % mod; n >>= 1; } return res % mod; }
测试链接:http://acm.hdu.edu.cn/showproblem.php?pid=1061


#include <iostream> using namespace std; //x^n % mod int quickPower(int x, int n, int mod) { int t = x, res = 1; while (n) { if (n & 1) res = ((res % mod) * (t % mod)) % mod; t = ((t % mod) * (t % mod)) % mod; n >>= 1; } return res % mod; } int main() { int N; cin >> N; while (N--) { int n; cin >> n; cout << quickPower(n, n, 10) << endl; } return 0; }
3.矩阵快速幂
首先要知道:矩阵乘法_百度百科,简单的说矩阵就是二维数组,数存在里面,相乘就是 横*竖,交叉位置是结果位置。
对着例子好理解些:
要注意的是:A的行数与B的列数必须相同才可以进行乘法
矩阵乘法:
//A :m行*n列;B:n行*m列 int** MatMulti(int **A, int **B, int m, int n) { int **C = new int*[n + 1]; for (int i = 1; i <= n; i++) { C[i] = new int[n + 1]; memset(C[i], 0, sizeof(int)*(n + 1)); } for (int i = 1; i <= m; i++) { for (int j = 1; j <= m; j++) { for (int k = 1; k <= n; k++) { if (A[i][k] == 0 || B[k][j] == 0)continue; C[i][j] += A[i][k] * B[k][j]; } } } return C; }
完整测试代码:


#include <iostream> using namespace std; //A :m行*n列;B:n行*m列 int** MatMulti(int **A, int **B, int m, int n) { int **C = new int*[n + 1]; for (int i = 1; i <= n; i++) { C[i] = new int[n + 1]; memset(C[i], 0, sizeof(int)*(n + 1)); } for (int i = 1; i <= m; i++) { for (int j = 1; j <= m; j++) { for (int k = 1; k <= n; k++) { if (A[i][k] == 0 || B[k][j] == 0)continue; C[i][j] += A[i][k] * B[k][j]; } } } return C; } /*2 3 1 2 3 4 5 6 1 4 2 5 3 6*/ int main() { int **a, **b; int m, n; cin >> m >> n; a = new int*[m + 1]; b = new int*[n + 1]; for (int i = 1; i <= m; i++) { a[i] = new int[n + 1]; } for (int i = 1; i <= n; i++) { b[i] = new int[m + 1]; } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { cin >> a[i][j]; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> b[i][j]; } } int **c = MatMulti(a, b, m, n); for (int i = 1; i <= m; i++) { for (int j = 1; j <= m; j++) { cout << c[i][j] << " "; } cout << endl; } return 0; }
上面只是简单的计算矩阵的乘积,会感觉很抽象,因为上述矩阵并没有具体的含义。
以最常见的斐波那契数列为例:
F[n] = F[n-1] + F[n-2]. 由 F[0] = 0, F[1] = 1,可以递推后面的所有数。
用斐波那契数列的递推式表示成矩阵就得到下面的式子 :
将 记作矩阵A
于是有
再变一下形
然后我们只需要算出 A^n,就可以求出Fn了。
题目链接:http://poj.org/problem?id=3070(这是POJ题目里给的提示,很人性化了。)
#include <iostream> using namespace std; void initialize(int m[][2]) { m[0][0] = 1; m[0][1] = 1; m[1][0] = 1; m[1][1] = 0; } void MatrixMulti(int m1[][2],int m2[][2],int m[][2]) { int t[2][2] = {0}; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { t[i][j] = (t[i][j] + m1[i][k]%10000 * m2[k][j]%10000) % 10000; } } } for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { m[i][j] = t[i][j]; } } } int MatrixQuickPower(int m[][2],int n) { int res[2][2] = { {1,0},{0,1} }; while (n) { if (n & 1) MatrixMulti(res, m, res); MatrixMulti(m, m, m); n >>= 1; } return res[0][1]; } int main() { int n, m[2][2]; while (cin >> n) { if (n == -1)break; initialize(m); cout << MatrixQuickPower(m, n) << endl; } return 0; }