// 快速幂://顾名思义,快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), //与朴素的O(N)相比效率有了极大的提高#include <cstdio>#define MOD 1000000007int Pow(int a,int n) // recursive solution{ if(n == 0) return 1; int temp = Pow(a,n >> 1); temp = temp * temp % MOD; if(n & 1) temp = temp * a % MOD; return temp;}int Foo(int a,int n){ int temp = 1; int y = a; while(n) { if(n&1) temp = temp * y % MOD;// 利用二进制的思想n^(10) = n^(B1010) // 出现n&1 此时y表示n^(2) n^(2) * n^(8) = n^(10) y = y * y % MOD; n = n >> 1; } return temp;}int main(){ int a,b; while(1) { scanf("%d%d",&a,&b); printf("%d\n",Foo(a,b)); printf("%d\n",Pow(a,b)); } return 0;}利用快速幂的思想求矩阵M的N的次方题目描述:https://hihocoder.com/problemset/problem/1504?sid=1074922在8x8的国际象棋棋盘上给定一只骑士(俗称“马”)棋子的位置(R, C),小Hi想知道从(R, C)开始移动N步一共有多少种不同的走法。 输入第一行包含三个整数,N,R和C。对于40%的数据, 1 <= N <= 1000000对于100%的数据, 1 <= N <= 1000000000 1 <= R, C <= 8输出从(R, C)开始走N步有多少种不同的走法。由于答案可能非常大,你只需要输出答案模1000000007的余数。样例输入2 1 1样例输出12#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define MOD 1000000007int Pow(int r,int c,int n){//Map to set from x to yconst int buff[8][2] = {{-1,+2},{-1,-2},{+1,+2},{+1,-2},{+2,-1},{-2,-1},{+2,+1},{-2,+1}};long long Map[64][64] = {0};long long Result[64] = {0};for(int i = 0;i < 8;i ++)for(int j = 0;j < 8;j ++){for(int k = 0;k < 8;k ++){ int x = i + buff[k][0]; int y = j + buff[k][1]; if(x >= 0 && x < 8 && y >= 0 && y < 8) { Map[i * 8 + j][x * 8 + y] = 1; }}}// Map ^ n then sum the arrayfor(int i = 0;i < 64;i ++) Result[i] = 1;while(n){if(n & 1){long long t[64] = {0};for(int i = 0;i < 64;i ++) for(int j = 0;j < 64;j ++) { t[i] = t[i] + Map[i][j] * Result[j] % MOD; }for(int i = 0;i < 64;i ++)Result[i] = t[i] % MOD;}int temp[64][64] = {0};for(int i = 0;i < 64;i ++)for(int j = 0;j < 64;j ++){long long t = 0;for(int k = 0;k < 64;k ++)t += Map[i][k] * Map[k][j] % MOD;temp[i][j] = t % MOD;}for(int i = 0;i < 64;i ++)for(int j = 0;j < 64;j ++)Map[i][j] = temp[i][j];n = n >> 1;}return Result[r * 8 + c];}int main(){int N,R,C;scanf("%d%d%d",&N,&R,&C);R --,C --;printf("%d\n",Pow(R,C,N));return 0;}
DFS计数问题,题目描述:https://hihocoder.com/problemset/problem/1560?sid=1156184
#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>using namespace std;#define MOD 1000000007long long aans = 0;long long A[10][10] = {0};long long AA[10][10] = {0};long long min_(long long n,long long m){ return n < m ? n : m;}void power(long long n){ while(n) { if(n&1) { long long tmpp[10][10] = {0}; for(int i = 0;i < 10;i ++) for(int j = 0;j < 10;j ++) for(int k = 0;k < 10;k ++) tmpp[i][j] += A[i][k] * AA[k][j] % MOD; for(int i = 0;i <= 9;i ++) for(int j = 0;j <= 9;j ++) A[i][j] = tmpp[i][j] % MOD; } long long tmp[10][10] = {0}; for(int i = 0;i < 10;i ++) for(int j = 0;j < 10;j ++) { long long t = 0; for(int k = 0;k < 10;k ++) t += AA[i][k] * AA[k][j] % MOD; tmp[i][j] = t % MOD; } for(int i = 0;i < 10;i ++) for(int j = 0;j < 10;j ++) AA[i][j] = tmp[i][j]; n = n >> 1; } return;}int main(){ long long n,m; cin >> n >> m; for(int i = 0;i <= 9;i ++) { for(int j = 0;j <= 9;j ++) { if(i == 0) A[i][j] = 0; else if(j == 0) { if(i == 0) A[i][j] = 0; else if(i <= min_(9,m)) A[i][j] = 1; } else { if(i*j <= m) A[i][j] = 1; } } } for(int i = 0;i <= 9;i ++) { for(int j = 0;j <= 9;j ++) { if(i == 0) { if(j <= min_(9,m)) AA[i][j] = 1; } else if(j == 0) { if(i <= min_(9,m)) AA[i][j] = 1; } else { if(i*j <= m) AA[i][j] = 1; } } } if(n == 1) cout << min_(9,m); else if(n == 2) { for(int i = 0;i <= 9;i ++) for(int j = 0;j <= 9;j ++) aans = aans + A[i][j] % MOD; cout << aans % MOD << endl; } else{ power(n-2); for(int i = 0;i <= 9;i ++) for(int j = 0;j <= 9;j ++) aans = aans + A[i][j] % MOD; cout << aans % MOD << endl; } return 0;}
0 0