P5491 【模板】二次剩余
实际上是做法的归纳
一切皆是结论性的,没有证明!
模 意义下的二次剩余有 个,二次非剩余也恰有那么多
考虑解关于 的同余方程
当 时, 是唯一解
当 时,若方程有解,则只有两个互为相反数的解
判断有无解:欧拉准则
考虑 模 的结果
由
只其结果只为 或
时有解, 时无解
求解的话,先随机找到一个 满足 为二次非剩余,令
类似实部和虚部,定义这个
有
证明的话,有
然后
为偶数,开方就很容易了
具体实现弄上“复数”即可
且 的“虚部” 为
#include <cstdio> #include <algorithm> #include <iostream> #define IN inline using namespace std; typedef long long LL; int T, n, p; LL i2; struct complex { LL x, y; IN complex(LL _x, LL _y) {x = _x, y = _y;} IN bool operator == (complex a) {return (a.x == x && a.y == y);} IN complex operator * (complex a) { return complex((a.x * x % p + a.y * y % p * i2 % p) % p, (a.x * y % p + a.y * x % p) % p); } }; IN complex power(complex x, int y) { complex s = complex(1, 0); for(; y; y >>= 1, x = x * x) if (y & 1) s = s * x; return s; } IN int check(LL a) {return power(complex(a, 0), p - 1 >> 1) == complex(1, 0);} IN void solve() { if (!n) {printf("0\n"); return;} if (power(complex(n, 0), p - 1 >> 1) == complex(p - 1, 0)) {printf("Hola!\n"); return;} LL a = rand() % p; while (!a || check((a * a % p - n + p) % p)) a = rand() % p; i2 = (a * a % p - n + p) % p; int x0 = power(complex(a, 1), p + 1 >> 1).x, x1 = p - x0; if (x0 > x1) swap(x0, x1); printf("%d %d\n", x0, x1); } int main() { scanf("%d", &T); for(; T; --T) scanf("%d%d", &n, &p), solve(); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
2021-07-15 LG P4213【模板】杜教筛(Sum)
2020-07-15 JZOJ 排列统计