zoukankan      html  css  js  c++  java
  • 二分幂/快速幂

      二分幂又叫快速幂

    它的主要功能是计算 a^b%p (模 p可有可无) 。

    时间复杂度为O(logN)


    举个例子:不妨设 a=107,b=102,p=1000000007,如果我们求出了 x=a^51%p, 那么 x^2%p就是答案。

    那么下面就是求 a^51:我们求出了 x=a^25,那么 x^2*a就是答案

    快速幂非递归(循环+位运算)实现:
     1 long long ksm(long long a,long long b,long long mod)
     2 {
     3    long long ans=1;
     4    a%=mod;
     5    while(b>0)
     6    {
     7        if(b&1)
     8        {
     9            ans=ans*a%mod;
    10        }
    11        b>>=1;
    12        a=a*a%mod;
    13    }
    14    return ans;
    15 }
     1 快速幂递归实现:
     2 int power(int a, int n){
     3     int ans;
     4     if(n==0) ans=1;
     5     else
     6     {  ans=power(a*a, n/2);
     7        if(n%2==1) ans*=a;
     8      }
     9      return ans;
    10 }

    所谓二分求幂,即是将b次幂用二进制表示,当二进制位k位为1时,需要累乘a的2^k次方。

    (1)(x+y)%p=(x%p+y%p)%p; 

    (2)(x-y)%p=((x%p-y%p)%p+p)%p; 

    (3)x*y%p=((x%p)*(y%p))%p。

    http://acm.hdu.edu.cn/showproblem.php?pid=4506

    给你n个数字,分别是a1,a2,a3,a4,a5……an,这些数字每过一个单位时间就会改变,假设上一个单位时间的数字为a1’,a2’,a3’……an’,那么这个单位时间的数字a[i] = a[i - 1]’ * K(i == 1的时候a[1] = a[n]’ * K),其中K为给定的系数。
    现在的问题就是求第t单位时间的时候这n个数字变成了什么了?由于数字可能会很大,所以只要你输出数字对10^9 + 7取余以后的结果。

    输入数据第一行是一个正整数T,表示有T组测试数据;
      每组数据有两行,第一行包含输入三个整数n, t, k,其中n代表数字个数,t代表第t个单位时间,k代表系数;第二行输入n个数字ai,代表每个数字开始的时候是多少。

      [Technical Specification]
      T <= 100
      1 <= n <= 10 ^ 4
      0 <= t <= 10 ^ 9  其中 t = 0 表示初始状态
      1 <= k <= 10 ^ 9
      1 <= ai<= 10 ^ 9

     将乘系数与移动分开,由于乘的系数为a^b可能很大,所以用long long 和快速幂

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cmath"
     4 using namespace std;
     5 long long fun(long long a,long long b)
     6 {
     7 
     8     long long sum=1;
     9     while(b>0)
    10     {
    11        if(b&1)
    12        {
    13            sum=sum*a%1000000007;
    14        }
    15        a=a*a%1000000007;
    16        b>>=1;
    17     }
    18     return sum;
    19 }
    20 int main()
    21 {
    22 
    23    long long T,t,n,k,a[10000];
    24    cin>>T;
    25    int i;
    26    while(T--)
    27    {
    28       cin>>n>>t>>k;
    29       long long c=fun(k,t);//快速幂得系数
    30       for(i=0;i<n;i++)
    31         {
    32             cin>>a[i];
    33             a[i]=a[i]*c%1000000007;
    34         }
    35         t%=n;//减少运算
    36         while(t--)//移动
    37         {
    38             long long x=a[n-1];
    39             for(i=n-1;i>=0;i--)
    40             {
    41                 a[i]=a[i-1];
    42             }
    43             a[0]=x;
    44         }
    45         for(i=0;i<n;i++)
    46         {
    47             if(i==n-1)
    48                {
    49                 cout<<a[i]<<endl;
    50                 break;
    51                }
    52             cout<<a[i]<<' ';
    53         }
    54    }
    55    return 0;
    56 }
     http://poj.org/problem?id=3070
    计算第n个斐波那契数的后四位所表示的整数
    输入n 0 ≤ n ≤ 1,000,000,000 输入-1结束

    An alternative formula for the Fibonacci sequence is

    
    

    .

    As a reminder, matrix multiplication is associative, and the product of two 2 × 2 matrices is given by

    .

    Also, note that raising any 2 × 2 matrix to the 0th power gives the identity matrix:

    .

    
    

    Time Limit: 1000MS Memory Limit: 65536K

     1 class matrix
     2 {
     3 public:
     4         int a[2][2];
     5         matrix()
     6         {
     7                 a[0][0]=a[0][1]=a[1][0]=1;
     8                 a[1][1]=0;
     9         }
    10 };
    11 matrix multi(matrix a,matrix b)//矩阵的乘法
    12 {
    13     matrix temp;
    14     for(int i=0;i<2;i++)
    15         for(int j=0;j<2;j++){
    16             temp.a[i][j]=0;
    17             for(int k=0;k<2;k++)
    18                 temp.a[i][j]+=a.a[i][k]*b.a[k][j];
    19             if(temp.a[i][j]>10000)
    20               temp.a[i][j]=temp.a[i][j]%10000;
    21         }
    22     return temp;
    23 }
    24  matrix power(int n)///矩阵的n次幂
    25 {
    26         matrix temp,s;
    27         temp.a[0][1]=temp.a[1][0]=0;
    28         temp.a[1][1]=1;
    29         while(n!=0)///矩阵的快速幂
    30         {
    31           if(n%2!=0)
    32             temp=multi(temp,s);
    33             s=multi(s,s);
    34             n=n/2;
    35         }
    36         return temp;
    37 }
    38 int main()
    39 {
    40         int n;
    41         matrix  ans;
    42         while(scanf("%d",&n)&&n!=-1){
    43                ans=power(n);
    44                printf("%d
    ",ans.a[1][0]);
    45         }
    46          return 0;
    47 }

    同余运算及其基本性质
    如果两个数a和b之差能被m整除,那么我们就说a和b对模数m同余(关于m同余)。
    比如,100-60除以8正好除尽,我们就说100和60对于模数8同余。
    它的另一层含义就是说,100和60除以8的余数相同。a和b对m同余,
    我们记作a≡b(mod m)。比如,刚才的例子可以写成100≡60(mod 8)。
    你会发现这种记号到处都在用,比如和数论相关的书中就经常把
    a mod 3 = 1写作a≡1(mod 3)。

    如果a≡b(mod m),x≡y(mod m),则a+x≡b+y(mod m)
    如果a≡b(mod m),x≡y(mod m),则ax≡by(mod m)
    如果ac≡bc(mod m),且c和m互质,则a≡b(mod m)

  • 相关阅读:
    前后端分离后的前端时代
    解决input[type=file]打开时慢、卡顿问题
    es6快速入门
    jsonp的原理和实现
    减少前端代码耦合
    【css技能提升】css高级技巧
    vetur插件提示 'v-for' directives require 'v-bind:key' directives.错误的解决办法
    ES6的开发环境搭建
    netCore webapi Uow实现方式
    netcore webapi统一配置跨域问题
  • 原文地址:https://www.cnblogs.com/kimsimple/p/6384719.html
Copyright © 2011-2022 走看看