从BZOJ2242看数论基础算法:快速幂,gcd,exgcd,BSGS
其实就是三个板子
1.快速幂
快速幂,通过把指数转化成二进制位来优化幂运算,基础知识
2.gcd和exgcd
gcd就是所谓的辗转相除法,在这里用取模的形式体现出来
\(gcd(a,b)\),因为b中的a对答案没有贡献,考虑把b变成\(b-(b/a)*a\)答案是一样的
所以就可以变成了\(gcd(b,a%b)\),保证大的数在前面,这样当小的数变成0,大的数就是最大公约数
exgcd就是解线性方程\(ax+by=c\)
有解的条件是\(c\%gcd(a,b)=0\)
然后考虑gcd的过程对上面的方程进行转化
\(ax+by=gcd(a,b)=gcd(b,a\%b)=bx'+(a\%b)y'\)
这里把\(a%b\)变成\(a-a/b*b\),就变成了
\(ax+by=bx'+ay'-(a/b)*b*y'\)
解得\(x=y',y=x'-(a/b)*y'\)
然后当b变成1的时候,x=1,y=0
递归执行就可以解出来了
那么最小非负解是啥?
首先把x,y乘上\(c/gcd(a,b)\)变成原方程的特解
然后就可以得到通解
\(x = x' + b/gcd(a,b)*t\)
\(y = y' - a/gcd(a,b)*t\)
发现这个时候一定满足\(ax+by=c\),最小非负解也就很好求了
3.BSGS
挺有意思的一个东西,可以求解离散数对问题
\(a^x=b(mod\ c)\),给出a,b,c求x
大多数时候会保证c是质数
这个时候我们怎么办?
发现有用的x只有c-1个
考虑把x分解成ir+m的形式
然后式子变成\(a^{ir}=b*a^{-m}(mod\ c)\)
如果令\(r=\sqrt{c}\),那么枚举i并在hashtable里面查找有没有对应的m就可以了
这样的复杂度是\(\sqrt{c}\)的
//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
int y, z, P;
int add(int a, int b) {
return (a += b) >= P ? a - P : a;
}
int sub(int a, int b) {
return (a -= b) < 0 ? a + P : a;
}
int mul(int a, int b) {
return 1ll * a * b % P;
}
int fast_pow(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = mul(res, a);
b >>= 1;
a = mul(a, a);
}
return res;
}
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
void exgcd(int a, int b, ll &x, ll &y) {
if (!b) {x = 1, y = 0; return;}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
void work1() {
Read(y), Read(z), Read(P);
Write(fast_pow(y, z));
putchar('\n');
}
void work2() {
Read(y), Read(z), Read(P);
int g = gcd(y, P);
if (z % g) {
printf("Orz, I cannot find x!\n");
} else {
ll a, b;
exgcd(y, P, a, b);
a *= z / g;
a = (a % (P / g) + P / g) % (P / g);
Write(a);
putchar('\n');
}
}
map<int, int> mp;
void work3() {
Read(y), Read(z), Read(P);
y %= P, z %= P;
if (!y) {
printf("Orz, I cannot find x!\n");
return;
}
int w = sqrt(P), now = z;
mp.clear();
fu(i, 0, w) {
mp[now] = i;
now = mul(now, y);
}
now = fast_pow(y, w);
int tmp = now;
fu(i, 1, w) {
if (mp.count(tmp)) {
Write(i * w - mp[tmp]);
putchar('\n');
return;
}
tmp = mul(tmp, now);
}
printf("Orz, I cannot find x!\n");
}
int main() {
int T, op;
Read(T); Read(op);
if (op == 1) while (T--) work1();
else if (op == 2) while (T--) work2();
else while (T--) work3();
return 0;
}
从BZOJ2242看数论基础算法:快速幂,gcd,exgcd,BSGS的更多相关文章
- 【BZOJ4002】[JLOI2015]有意义的字符串(数论,矩阵快速幂)
[BZOJ4002][JLOI2015]有意义的字符串(数论,矩阵快速幂) 题面 BZOJ 洛谷 题解 发现我这种题总是做不动... 令\(A=\frac{b+\sqrt d}{2},B=\frac{ ...
- 【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)
[BZOJ2432][NOI2011]兔农(数论,矩阵快速幂) 题面 BZOJ 题解 这题\(75\)分就是送的,我什么都不想写. 先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后 把它减 ...
- 数论基础算法总结(python版)
/* Author: wsnpyo Update Date: 2014-11-16 Algorithm: 快速幂/Fermat, Solovay_Stassen, Miller-Rabin素性检验/E ...
- Java 算法-快速幂
1 什么是快速幂? 快速幂,顾名思义就是快速的求次幂,例如:a^b,普通的算法就是累乘,这样的计算方法的时间复杂度就是O(n),而快速幂的方法使得次幂的计算方法的时间复杂度降低到O(logn). 假 ...
- ACM | 算法 | 快速幂
目录 快速幂 快速幂取模 矩阵快速幂 矩阵快速幂取模 HDU1005练习 快速幂 幂运算:\(x ^ n\) 根据其一般定义我们可以简单实现其非负整数情况下的函数 定义法: int Pow ( ...
- 【POJ 1845】Sumdiv——数论 质因数 + 分治 + 快速幂
(题面来自luogu) 题目描述 输入两个正整数a和b,求a^b的所有因子之和.结果太大,只要输出它对9901的余数. 输入格式 仅一行,为两个正整数a和b(0≤a,b≤50000000). 输出格式 ...
- 【数论】【快速幂】CODEVS 2952 细胞分裂 2
裸快速幂取模,背诵模板用. #include<cstdio> using namespace std; typedef long long LL; LL n=,m,q; LL Quick_ ...
- 【数论】【快速幂】bzoj1008 [HNOI2008]越狱
根据 高中的数学知识 即可推出 ans=m^n-m*(m-1)^(n-1) .快速幂取模搞一下即可. #include<cstdio> using namespace std; typed ...
- ACM学习历程—HDU5667 Sequence(数论 && 矩阵乘法 && 快速幂)
http://acm.hdu.edu.cn/showproblem.php?pid=5667 这题的关键是处理指数,因为最后结果是a^t这种的,主要是如何计算t. 发现t是一个递推式,t(n) = c ...
随机推荐
- jQuery Ajax总结
jQuery对Ajax的操作进行了封装.jQuery中\(.ajax()属于最底层的方法,这个放在后面说,首先看看封装了\).ajax()的方法. load()方法 load()可以远程载入HTML并 ...
- 如何将本地的项目上传到git
如何将本地的项目上传到git 1 进入项目文件夹,把目录变为git仓库 git init 2 把文件添加到版本库中 git add . 3 把版本提交到版本库 git commit -m 'first ...
- Linux加载/usr/local/lib中的so库
> https://my.oschina.net/u/2306127/blog/1617233 > https://blog.csdn.net/csfreebird/article/det ...
- scp 上传 下载 文件
linux 中的ssh命令: scp 可以用来上传本地文件到远程服务器 或下载远程服务器中的文件到本地 1. 上传本地文件到远程服务器 scp readme.md user@www.*****.com ...
- 1-15-1 RAID磁盘阵列的原理和搭建
大纲: 1.1-1-企业级RAID磁盘阵列 RAID磁盘阵列的原理 RAID0,1,5,10的搭建 硬件RAID卡 1.2-1-使用廉价的磁盘搭建RAID磁盘阵列 实战-配置RAID0带区卷 ==== ...
- 个人知识管理系统Version1.0开发记录(03)
demo 设 计 一个知识点demo,在数据库和用户界面的互动事件.分三个层次,数据存储,数据方法工具,数据呈现界面.这一次先完成数据存储,按以下逻辑实现.工具:eclipse,oracle数据库, ...
- Dubbo + Zookeeper 简单配置
Dubbo + Zookeeper Zookeeper 下载及配置 下载到本机/usr/local目录 wget https://mirrors.tuna.tsinghua.edu.cn/apache ...
- 【MySQL】Error 1264: out of range value for column
此问题是插入的整型数字超出了范围. 比如设置表格的数据类型:cust_fax integer(10) not null 当插入以下数字的时候会抛出标题所说的错误: insert into databa ...
- UML_03_类图
一.前言 类图是UML结构图,在类和接口的层次上显示设计系统的结构,显示它们的特性.约束和关系等,是定义其它图的基础. 二.类图 如上图,在类图中表示方法如下: 斜体 :抽象类.抽象方法 下划线 :静 ...
- canvas 画布 文字描边
总结一下,canvas 画布 文字描边的2种方法以及其不同的视觉效果: 效果图: 具体代码: <canvas id="canvas" width="800" ...