BZOJ 2480 && 3239 && 2995 高次不定方程(高次同余方程)
链接
虽然是个三倍经验题(2333),但是只有上面这道(BZOJ2480)有 p = 1 的加强数据,推荐大家做这道。
题解
这是一道BSGS(Baby Step Giant Step)的棵题,要考虑的细节还是很多的……
先讲一下题解吧。
由于每个版本的题设的字母都不尽相同,所以……在下文中我使用的方程是
\]
考虑暴力枚举,可以证明,\(A^x \bmod C\)是周期性的,且周期长度不超过\(C\)。那么暴力枚举\([0, C - 1]\)的整数就可以得到答案。
考虑优化——BSGS算法。
将所有要枚举的数分成\(n = \lfloor \sqrt C \rfloor\)块,每块有\(m\)个数。
如果我们按块枚举,在第\(i\)块中的倒数第\(y\)个位置找到了答案,则有:
\]
可以把\(A^{-y}\)移到等式右边,得:
\]
那么可以\(O(m)\)枚举\(y \in [1, m]\),将得到的所有\(A^y*B \bmod C\)加入哈希表,然后\(O(n)\)枚举\(i\)得到\(A^{i * m} \bmod C\),如果在哈希表中能找到它对应的\(y\),则\(i * m - y\)就是一个答案。
听起来没有问题?
很好写?
其实还有一个问题……
上面的叙述其实是默认\(A, C\)互质的……
而当\(A, C\)不互质,\(A^{-1} \pmod C\)即A关于C的逆元是不存在的,所以不能吧\(A^{-y}\)看作一个数移到等式右边!
那怎么办呢……?
必须强行让\(A, C\)互质了!
下文为了方便,搞了个\(A^x\equiv B_1\pmod {C_1}\)的等价式子$$A^x + C_1 * y = B_1$$
把等式两边同时除以\(g_1 = gcd(A, C)\):
\]
其中\(C_2 = \frac{C_1}{g_1}, B_2 = \frac{B_1}{g_1}\)。
显然,如果\(B_1 \bmod g_1 \not= 0\),则无解。
这样是不是就完成了呢?
不是!
此时\(A\)和\(C_2\)不一定互质,例如\(A = 12, C_1 = 9, C_2 = 3\),\(12\)和\(3\)就不互质。
那么我们要不断地往下除\(gcd(A, C)\),直到二者互质,这个操作的次数是\(O(\log n)\)的。
最后,我们得到的方程像这样:
\]
设\(D = \frac{A^{cnt}}{d_1d_2d_3...d_n}\),则把\(D\)移到等式右边:
\]
此时\(A\)和\(C_n\)是互质的,解这个方程就好了。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
#define enter putchar('\n')
#define space putchar(' ')
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c > '9' || c < '0')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int P = 999979, N = 100005; //P是哈希表用的质数
ll A, B, C, cnt, D;
ll adj[P], nxt[N], num[N], val[N], stk[N], top;
ll gcd(ll a, ll b){
return b ? gcd(b, a % b) : a;
}
void exgcd(ll a, ll b, ll &x, ll &y){
if(!b) return (void)(x = 1, y = 0);
exgcd(b, a % b, y, x);
y -= a / b * x;
}
ll inv(ll a, ll p){ //求逆元
ll x, y;
exgcd(a, p, x, y);
return (x % p + p) % p;
}
void clear(){ //高效率清空哈希表
while(top) adj[stk[top--]] = 0;
}
ll find(ll x){ //找到哈希表中val最大(即最后添加)、num == x的元素的val
for(ll i = adj[x % P]; i; i = nxt[i])
if(num[i] == x) return val[i];
return -1;
}
void insert(ll x, ll y){ //向哈希表插入一个元素,num = x,val = y
stk[++top] = x % P;
nxt[top] = adj[stk[top]];
adj[stk[top]] = top;
num[top] = x;
val[top] = y;
}
bool check(){ //使AC互质,同时排除部分无解情况(B % gcd(A, C) != 0)
if(C == 0 || (A == 0 && B != 0)) return 0;
cnt = 0, D = 1;
for(ll g = gcd(A, C); g != 1; g = gcd(A, C))
if(B % g) return 0;
else cnt++, B /= g, C /= g, D = D * A / g % C;
B = B * inv(D, C) % C;
return 1;
}
bool force(){ //为了排除解小于cnt的情况,先进行小范围暴力
ll sum = 1 % C; //一个神犇给BZOJ2480加了一组 C == 1 的数据!
for(int i = 0; i <= 30; i++){
if(sum == B) return write(i), enter, 1;
sum = sum * A % C;
}
return 0;
}
int main(){
while(read(A), read(C), read(B), A + B + C != 0){
A %= C, B %= C;
if(force()) continue;
else if(!check()) puts("No Solution");
else{
clear();
bool solved = 0;
ll sum = 1, n = sqrt(C), m = ceil((double)C / n); //分成n块,每块m个
for(ll i = 1; i <= m; i++){ //将 pow(A, i) * B 插入哈希表
sum = sum * A % C;
insert(sum * B % C, i);
}
for(ll i = 1, tot = 1, y; i <= n && !solved; i++){ //检查每个 pow(A, i * m) 是否在哈希表中
tot = tot * sum % C;
if((y = find(tot)) != -1){
write(i * m - y + cnt), enter;
solved = 1;
}
}
if(!solved) puts("No Solution");
}
}
return 0;
}
BZOJ 2480 && 3239 && 2995 高次不定方程(高次同余方程)的更多相关文章
- 高次不定方程BSGS算法
学习数学真是一件赛艇的事. BSGS名字听起来非常有意思,力拔山兮气盖世,北上广深,小步大步...算法其实更有意思,它是用来求解一个方程的 \(A^x≡B mod P\) 是不是特别眼熟,有几个式子长 ...
- 【BZOJ】3239: Discrete Logging
http://www.lydsy.com/JudgeOnline/problem.php?id=3239 题意:原题很清楚了= = #include <bits/stdc++.h> usi ...
- [BZOJ 2480] [SPOJ 3105] Mod
Description 已知数 \(a,p,b\),求满足 \(a^x\equiv b\pmod p\) 的最小自然数 \(x\). Input 每个测试文件中最多包含 \(100\) 组测试数据. ...
- bzoj 2480——扩展BSGS
题意 给定 $a,b$ 和模数 $p$,求整数 $x$ 满足 $a^x \equiv b(mod \ p)$,不保证 $a,p$ 互质. (好像是权限题,可见洛谷P4195 分析 之前讲过,可以通过 ...
- 【BZOJ】【2480】【SPOJ 3105】Mod
扩展BSGS Orz zyf……然而他的题解对AC大神的题解作了引用……而坑爹的百度云……呵呵了... 扩展BSGS模板题 /************************************* ...
- [CQOI2018]破解D-H协议
嘟嘟嘟 这不就是个bsgs板儿嘛. 顺便就复习了一下bsgs和哈希表. 头一次觉得我的博客这么好用,一下就懂了:数论学习笔记之高次不定方程 这里再补充几点: 1.关于这一段代码: int S = sq ...
- 数论知识总结——史诗大作(这是一个flag)
1.快速幂 计算a^b的快速算法,例如,3^5,我们把5写成二进制101,3^5=3^1*1+3^2*2+3^4*1 ll fast(ll a,ll b){ll ans=;,a=mul(a,a)))a ...
- 【[TJOI2007]可爱的质数】
题目 用一道板子题来复习一下\(bsgs\) \(bsgs\)用于求解形如 \[a^x\equiv b(mod\ p)\] 这样的高次不定方程 由于费马小定理的存在,我们可是直接暴力扫一遍\(p\), ...
- Noip数学整理
目录 Noip数学整理 序 1 取模相关 2 质数相关 3.基本操作 4.方程相关 5.数列相关 6.函数相关 Noip数学整理 序 因为某些原因, Noip对于数学方面的考纲仅停留在比较小的一部分, ...
随机推荐
- SQL Server聚合函数与聚合开窗函数
以下面这个表的数据作为示例. 什么是聚合函数? 聚合函数:聚合函数就是对一组值进行计算后返回单个值(即分组).聚合函数在计算时都会忽略空值(null). 所有的聚合函数均为确定性函数.即任何时候使用一 ...
- ASP.NET Core MVC中的IActionFilter.OnActionExecuting方法,可以获取Controller的Action方法参数值
用过ASP.NET Core MVC中IActionFilter拦截器的开发人员,都知道这是一个非常强大的MVC拦截器.最近才发现IActionFilter的OnActionExecuting方法,甚 ...
- x window的奥秘
阅读目录 了解自己机器上的 X Window 理解 display 和虚拟控制台 远程连接 X Server 理解 lightdm 和 X Window 桌面环境的启动过程 搞定 xauth X Se ...
- 2017-2018-2 20155230《网络对抗技术》实验1:PC平台逆向破解(5)M
1.直接修改程序机器指令,改变程序执行流程 2.通过构造输入参数,造成BOF攻击,改变程序执行流 3.注入Shellcode并执行 4.实验感想 注:因为截图是全屏所以右键图片在新的标签页打开观看更加 ...
- 20155338课程设计个人报告——基于ARM实验箱的Android交友软件的设计与实现
课程设计个人报告--基于ARM实验箱的Android交友软件的设计与实现 个人贡献 实验环境的搭建 代码调试 在电脑上成功运行 研究程序代码撰写小组报告 一.实验环境 1.Eclipse软件开发环境: ...
- python 回溯法 子集树模板 系列 —— 12、选排问题
问题 从n个元素中挑选m个元素进行排列,每个元素最多可重复r次.其中m∈[2,n],r∈[1,m]. 如:从4个元素中挑选3个元素进行排列,每个元素最多可重复r次. 分析 解x的长度是固定的,为m. ...
- 解决:Linux SSH Secure Shell(ssh) 超时断开的解决方法
转载:http://www.cnblogs.com/jifeng/archive/2011/06/25/2090118.html 修改/etc/ssh/sshd_config文件,找到 ClientA ...
- SpringMVC源码总结
SpringMVC源码总结 http://blog.csdn.net/z69183787/article/details/52816927
- REST-framework快速构建API--权限
我们在访问资源时,有些资源保密程度较高,需要特殊的人员才能访问.比如,获取公司的每日收入流水的API接口,只能CEO才能查看. 这时,我们就需要将资源设定权限了. REST-framework实现如下 ...
- 谷歌商店高级搜索 Google play advanced search
这个问题一直搜索了很久都没有答案,后来在StackOverflow上提问,很久也没人回答. 详见我的SO:https://stackoverflow.com/questions/52939493/ho ...