模板 快速幂|取余

前置知识

(1)如果将 aa 自乘一次,就会变成 a^2a2 。再把 a^2a2 自乘一次就会变成 a^4a4 。然后是 a^8a8…… 自乘 nn 次的结果是 a^{2^{n}}a2n 。对吧……

(2)a^xa^y = a^{x+y}axay=ax+y,这个容易。

(3)将 bb 转化为二进制观看一下:

比如 b = (11)_{10}b=(11)10? 就是 (1011)_{2}(1011)2? 。从左到右,这些 11 分别代表十进制的 8,2,18,2,1。可以说 a^{11} = a^8 × a^2 × a^1a11=a8×a2×a1。

为什么要这样表示?因为在快速幂的过程中,我们会把 aa 自乘为 a^2a2,然后 a^2a2 自乘为 a^4a4……像上面第一条说的。

取余运算有一些好用的性质,包括:

(A+B) \mod b = (A \mod b + B \mod b) \mod b(A+B)modb=(Amodb+Bmodb)modb

(A×B) \mod b = ((A \mod b) × (B \mod b)) \mod b(A×B)modb=((Amodb)×(Bmodb))modb

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<cmath>
const double PI = acos(-1.0);
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

ll quickPower(ll a, ll b,ll m) {   //计算a的b次方
    ll ans = 1;
    ll base = a;
    while (b) {
        if (b & 1) {
            ans *= base;
            ans %= m;
        }
        base *= base;
        base %= m;
        b >>= 1;   //注意是b>>=1 not b>>1
    }
    return ans;
}

int main() {
    ll b, p, k;
    scanf("%lld%lld%lld", &b, &p, &k);
    printf("%lld^%lld mod %lld=%lld",b,p,k,quickPower(b, p, k) % k);
    return 0;
}

洛谷 1010 幂次方

string run(int x, int i = 0, string s = string("")) {
    if (!x) return string("0");
    do if (x & 1) s = (i == 1 ? "2" : "2(" + run(i) + ")") + (s == "" ?"": "+") + s;
    while (++i, x >>= 1);
    return s;
}

int main() {
    int x;
    scanf("%d", &x);
    printf("%d", run(x));
    return 0;
}

太酷了

原文地址:https://www.cnblogs.com/hznumqf/p/12283516.html

时间: 2024-10-01 04:08:50

模板 快速幂|取余的相关文章

HDU1061_Rightmost Digit【快速幂取余】

Rightmost Digit Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 33161    Accepted Submission(s): 12696 Problem Description Given a positive integer N, you should output the most right digit of

poj 1845 Sumdiv (同余定理,快速幂取余)

链接:poj 1845 题意:求A^B的所有因子的和对9901取余后的值 如:2^3=8,8的因子有 1,2,4,8,所有和为15,取余后也是15 应用定理主要有三个: (1)整数的唯一分解定理: 任意正整数都有且只有一种方式写出其素因子的乘积表达式. A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)   其中pi均为素数 (2)约数和公式: 对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn) 有A的所有因子之和为 S = 

hdu 2817 A sequence of numbers(快速幂取余)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2817 题目大意:给出三个数,来判断是等差还是等比数列,再输入一个n,来计算第n个数的值. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #define m 200907 5 6 using namespace std; 7 8 __int64 fun(__int64 j,__int64 k) 9

快速幂取余 [转]

转自: http://blog.csdn.net/acm_code/article/details/38270829 求a^b mod c 算法1. 首先直接地来设计这个算法: int ans=1, i; for(i=1;i<=b;i++) ans*=a; ans%=c; 这个算法的时间复杂度体现在for循环中,为O(b). 这个算法存在着明显的问题,如果a和b过大,很容易就会溢出. 那么,我们先来看看第一个改进方案:在讲这个方案之前,要先有这样一个公式: a^b mod c=(a mod c)

LightOJ - 1282 - Leading and Trailing(数学技巧,快速幂取余)

链接: https://vjudge.net/problem/LightOJ-1282 题意: You are given two integers: n and k, your task is to find the most significant three digits, and least significant three digits of nk. 思路: 后三位快速幂取余,考虑前三位. \(n^k\)可以表示为\(a*10^m\)即使用科学计数法. 对两边取对数得到\(k*log

快速幂取余算法

下面是一个快速幂的介绍: 先贴一个秦九韶算法(Horner算法)的原理: 设有项的次函数 将前项提取公因子,得 再将括号内的前项提取公因子,得 如此反复提取公因子,最后将函数化为 令 ...... 则即为所求 下面是讲解快速幂的:(By  夜せ︱深   感谢作者) 快速幂取模算法 在网站上一直没有找到有关于快速幂算法的一个详细的描述和解释,这里,我给出快速幂算法的完整解释,用的是C语言,不同语言的读者只好换个位啦,毕竟读C的人较多~ 所谓的快速幂,实际上是快速幂取模的缩写,简单的说,就是快速的求

模板 快速幂取模

[模板]快速幂取模 1 long long quickmod(long long a,long long b,long long m) 2 { 3 long long ans = 1; 4 while(b)//用一个循环从右到左便利b的所有二进制位 5 { 6 if(b&1)//判断此时b[i]的二进制位是否为1 7 { 8 ans = (ans*a)%m;//乘到结果上,这里a是a^(2^i)%m 9 b--;//把该为变0 10 } 11 b/=2; 12 a = a*a%m; 13 } 1

POJ 1995 Raising Modulo Numbers (快速幂取余)

#include<iostream> using namespace std; int quick_mod(int a,int b,int m) //模板 { a=a%m; int ans=1; while(b) { if(b&1) { ans=(ans*a)%m; } b>>=1; a=(a*a)%m; } return ans; } int main() { int size; cin>>size; int m, h, a, b; while(cin>

快速幂取余

小余最近迷恋上了数论,他认为大素数的判定是非常迷人的,但是他的程序总是数一大就死循环= = ,结果找了一晚上,发现原来是求a*b%c这个环节上出现了错误,聪明的你能帮助可怜的小余求出这个问题吗? input 测试数组有多组,每行输入三个整数a,b,c(1<=a,b,c<2^64) output 对于每次输入,对应输出相应的结果即a*b%c的值.每个输出占一行. sample_input 1 2 3 2 3 4 1 1 1 sample_output 2 2 0 #include <ios