从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 ...
随机推荐
- e.target和e.currentTarget区别
直接上代码: body里: <div id="father"> father <div id="son"> son </div&g ...
- 使用MessageFormat替换字符中的占位符
使用String.format可以实现字符串的格式化功能,即将后面参数中的值替换掉format中的%s,%d这些值.但MessageFormat更为强大,不用管传入值是字符串还是数字,使用占位符即可. ...
- 常见HTTP状态(304,)
一.1XX(临时响应) 表示临时响应并需要请求者继续执行操作的状态码. 100(继续) 请求者应当继续提出请求.服务器返回此代码表示:已经收到请求的第一部分,正在等待其余部分. 101(切换协议) 请 ...
- 动态延迟加载网页元素jQuery插件scrollLoading
如果一个网页很长,那么该页面的加载时间也会相应的较长.而这里给大家介绍的这个jQuery插件scrollLoading的作用则是,对页面元素进行动态加载,通俗的说就是滚到哪就加载到哪,屏幕以下看不见的 ...
- phalcon: 项目地址/P(.*), 项目地址/Pbaidu 与 路由
phalcon: 项目地址/P(.*) 与 路由 有一个项目地址:因客户渠道不同,带的参数也不相同.当时想到的是伪静态规则,但是发现自己没有那么强大.该走phalcon路由规则,地址如下: www.x ...
- java开发中的重中之重-------mysql(基础篇)
介绍: mysql是目前世界上最流行的关系型数据库,在国内大的互联网公司都在使用mysql数据库,mysql经常被我们这样概述,“mysql是轻量级关系型数据库”,其实轻量级并不是说mysql是中小型 ...
- 设置了width和height的a元素在IE11与IE11以下浏览器中的不同渲染方式
#welcomeMiddleBtn { display: block; width: 73px; height: 120px; margin: 0px auto; } <a id="w ...
- 【Supervisor】Linux 后台进程管理利器
Linux的后台进程运行有好几种方法,例如nohup,screen等,但是,如果是一个服务程序,要可靠地在后台运行,我们就需要把它做成daemon,最好还能监控进程状态,在意外结束时能自动重启. su ...
- JavaScript数字和字符串转换示例
http://www.jb51.net/article/48465.htm 1. 数字转换为字符串 a. 要把一个数字转换为字符串,只要给它添加一个空的字符串即可: 复制代码代码如下: var n = ...
- 平衡二叉树(AVL)的实现,附可运行C语言代码
最近几月一直在自学C语言和数据结构,先是写了排序二叉树,觉得平衡二叉树作为一个经典数据结构,有必要实现一下. 网上看了些资料,在AVL和红黑树之间考虑,最后个人还是倾向于AVL. 不同于标准AVL的是 ...