快速幂的理解

// 快速幂:
//顾名思义,快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 
//与朴素的O(N)相比效率有了极大的提高
#include <cstdio>
#define MOD 1000000007
int 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 1000000007
int Pow(int r,int c,int n)
{
//Map to set from x to y
const 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 array
for(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 1000000007
long 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;
}








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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值