P4397聪明的燕姿 题解 & Miller~Rabin 质数判定
涉及质数的时间复杂度都是玄学的。
——题记
由整数唯一分解定理:
有该正整数的正约数为:
即我们要求有多少个数满足
然后就搜索
枚举第
优化
优化
扩:
首先:该算法本质上是一种随机化算法,能在
由费马小定理可知:对任意素数
考虑将其逆过来,对一个数
很明显是不可以的,一个反例就是
引入二次探测定理:对于质数
证明:
原式可以转换为
证毕
然后考虑结合两个定理,进行素数判断。
对于
否则将它分为
如果都满足,则我们认为这个数是质数
因为错误率是
所以我们可以选
当然,也可以选择背诵
可以保证
因为数已经定下来,所以可能会导致选的数是
最后,分析一下该算法时间复杂度:一次找到答案的时间不会超过
#include<bits/stdc++.h> #define int long long using namespace std; const int N=100005; int T,S; int ans[N],tot; bool prime[N]; int zs[N],idx; int ksm(int ds,int zs,int mod) { int re=1; while(zs) { if(zs&1) re=1ll*ds*re%mod; ds=1ll*ds*ds%mod; zs=zs/2; } return re; } bool MRtest(int x) { if(x%2==0||x<3) return x==2; int zs=x-1,sl=0; while(zs%2==0) zs=zs/2,sl++; int ud[3]={2,7,61}; for(int i=0;i<3;i++) { int v=ksm(ud[i],zs,x); if(v==1||v==x-1||v==0) continue; for(int j=1;j<=sl;j++) { v=1ll*v*v%x; if(v==x-1&&j!=sl){v=1;break;} if(v==1) return false; } if(v!=1) return false; } return true; } void dfs(int wz,int sum,int now) { if(sum==1) { ans[++tot]=now; return ; } if(sum<zs[wz]+1) return ; if(MRtest(sum-1)) ans[++tot]=(sum-1)*now; for(int i=wz;zs[i]*zs[i]<=sum;i++) { int zh=zs[i]+1,t=zs[i]; for(;zh<=sum;t*=zs[i],zh+=t) if(sum%zh==0) dfs(i+1,sum/zh,now*t); } } signed main() { prime[1]=true; for(int i=2;i<=100000;i++) { if(!prime[i]) zs[++idx]=i; for(int j=1;j<=idx&&zs[j]*i<=100000;j++) { prime[zs[j]*i]=true; if(i%zs[j]==0) break; } } while(scanf("%lld",&S)!=EOF) { tot=0; dfs(1,S,1); sort(ans+1,ans+tot+1); printf("%lld\n",tot); for(int i=1;i<=tot;i++) printf("%lld ",ans[i]); if(tot!=0) puts(""); } return 0; }
遇到质数的题,大胆
——后记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】