【模板】多项式开根(加强版)
VI.【模板】多项式开根(加强版)
这题和上题唯一的区别就是的取值——本题不一定为。
咋办呢?
我们观察到里面有一句话:
保证是下的二次剩余。
二次剩余?这是啥?能吃吗?
这时,你突然想起曾经看到过一道模板题:
于是你兴奋地点了进去,发现这正是我们需要的:求的根。
于是我们先讲解一下二次剩余的Cipolla算法。该算法仅应用于是奇质数的情形。
- 在上述方程中,有多少解?
我们先从简单的情形想起——假设它有两解,则一定有
于是
显然,不然就是重根了。
则必有,即与是在模意义下的相反数。
显然一个数只有唯一的相反数,故实际上二次剩余方程如果有解,则一定有两解。
(实际上是一个特例——它只有一根,于是可以特判掉,因此我们接下来讨论的都是非的)
- 怎样判断对于一个,其二次剩余方程是否有解?
如果一个关于的二次剩余方程有解,则我们称是的二次剩余。同理,如果无解,我们称其为的非二次剩余。
我们从费马小定理开始:
因为我们Cipolla算法应用的前提是是奇质数,所以,所以
显然是偶数,于是我们两边开根,得到
我们考虑当是二次剩余时,必有
因此是是二次剩余的必要条件。
我们考虑再证其充分性。设,其中是的原根。则必有。
而又有,故
所以
则必须是一个偶数来消掉分母上的。于是我们只要令即是二次剩余方程的一个根,故是二次剩余。
因此是是二次剩余的充分条件。
综上,,等价于是的二次剩余。
- 如何求根(Cipolla算法)
我们考虑随机出来一个使得不是二次剩余。这期望需要两次随机,因为每组相反数都对应着一组二次剩余,一共组相反数,故一共有个二次剩余,则剩下的数都不是二次剩余,故期望两次即可随机得到一个非二次剩余。
我们现在设一个。
等等,不是非二次剩余吗?那咋出来一个呢?
类比虚数概念,这个实际上也是一个虚数,它没有实际对应的数。
我们要证明几条引理:
- 。
因为是非二次剩余,所以,
所以
我们二项式展开后,除了与两项不存在以外,其它项全都存在因子,因此其,可以忽略,因此只保留两项。
于是
所以我们直接计算复数的次幂即可得到一个解,取相反数即可得到令一个解。
注意这里的取值应是,而不是正常复数中的!
时间复杂度期望为。
代码(【模板】二次剩余):
#include<bits/stdc++.h>
using namespace std;
int T,n,p,sqri;
struct cp{
int x,y;
cp(int a=0,int b=0){x=a,y=b;}
friend cp operator *(const cp &a,const cp &b){
return cp((1ll*a.x*b.x%p+1ll*a.y*b.y%p*sqri%p)%p,(1ll*a.y*b.x%p+1ll*a.x*b.y%p)%p);
}
};
int ksm(int x,int y){
int z=1;
for(;y;y>>=1,x=1ll*x*x%p)if(y&1)z=1ll*z*x%p;
return z;
}
cp ksm(cp x,int y){
cp z=cp(1,0);
for(;y;y>>=1,x=x*x)if(y&1)z=z*x;
return z;
}
bool che(int x){
return ksm(x,p>>1)==1;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&p),n%=p;
if(!n){puts("0");continue;}
if(!che(n)){puts("Hola!");continue;}
int a=rand()%p;
while(true){
sqri=(1ll*a*a%p-n+p)%p;
if(!a||che(sqri))a=rand()%p;
else break;
}
cp tmp=cp(a,1);
tmp=ksm(tmp,(p+1)>>1);
int u=tmp.x,v=(p-tmp.x)%p;
if(u>v)swap(u,v);
printf("%d %d\n",u,v);
}
return 0;
}
然后本题就只需要把迭代的初始值改成用Cipolla求出的二次剩余方程的根即可。
时间复杂度,代码就不贴了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?