首页 > 其他分享 >P4397聪明的燕姿 题解 & Miller~Rabin 质数判定

P4397聪明的燕姿 题解 & Miller~Rabin 质数判定

时间:2023-10-31 21:35:06浏览次数:36  
标签:燕姿 limits int 题解 质数 zs bmod equiv

涉及质数的时间复杂度都是玄学的。

——题记

传送门

由整数唯一分解定理:\(\coprod\limits_{i=1}^{k}p_i^{c_i}\)

有该正整数的正约数为:\(\coprod\limits_{i=1}^k(\sum\limits_{j=0}^{c_i}p_i^j)\)

即我们要求有多少个数满足 \(\coprod\limits_{i=1}^k(\sum\limits_{j=0}^{c_i}p_i^j)=S\)

然后就搜索 \(+\) 剪枝:

枚举第 \(i\) 个质数是否出现,出现多少次,显然是对的。

优化 \(1\) :当我们枚举到的质数大于 \(\sqrt S\) 时,我们直接判断 \(S-1\) 是不是质数即可,因为此时任意 \(p^2>S\)

优化 \(2\) :当要判断大于 \(1e6\) 的数是否为质数时,使用 \(Miller~Rabin\) 质数判定


扩:\(Miller~Rabin\) 质数判定:

首先:该算法本质上是一种随机化算法,能在\(O(k log^3 n)\)的时间复杂度下快速判断出一个数是否是素数,但具有一定的错误概率。不过在一定数据范围内,通过一些技巧可以使其不出错。

由费马小定理可知:对任意素数 \(p\) 和与其互质的整数 \(a\),有 \(a^{p-1}\equiv 1~(\bmod p)\)

考虑将其逆过来,对一个数 \(p\),随机选取一个小于它的 \(a\),若 \(a^{p-1}\equiv 1~(\bmod p)\),是否可以证明它是质数

很明显是不可以的,一个反例就是 \(561\)(当然这种数有无限个,可以去搜卡迈克尔数

引入二次探测定理:对于质数 \(p\) 若 \(x^2\equiv 1~(\bmod p)\),则小于 \(p\) 的解只有两个: \(x=1\) 或 \(x=p-1\)

证明:

原式可以转换为 \(x^2-1\equiv 0~(\bmod p)=>(x+1)(x-1)\equiv 0~(\bmod p)\),因为 \(p\) 的因数只有 \(1\) 和 \(p\),所以小于 \(p\) 的解只有 \(x=1\) 或 \(x=p-1\),

证毕

然后考虑结合两个定理,进行素数判断。

对于 \(p-1\),若它为奇数,直接特判

否则将它分为 \(2^k\times t\)(\(t\) 为奇数),随机选取一个 \(a\),先计算 \(a^t\),然后让其自乘,判断其解是否全为 \(1\) ,或者在非最后一个数的情况下出现 \(p-1\)

如果都满足,则我们认为这个数是质数

因为错误率是 \(\frac{1}{4}\)

所以我们可以选 \(2,3,5,7,11,13,17,19\) 多个数进行判断,降低错误率

当然,也可以选择背诵

\(int\) 范围内选 \(\{2,7,61\}\)

\(long~long\) 范围内选 \(\{2,325,9375,28178,450775,9780504,1795265022\}\)

可以保证 \(100\%\) 不会错

因为数已经定下来,所以可能会导致选的数是 \(p\) 的倍数,这是要特判,然后 \(continue\)


最后,分析一下该算法时间复杂度:一次找到答案的时间不会超过 \(\sqrt S\),所以时间复杂度是 \(O(Ans\sqrt S)\),玄学至极

#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;
}

遇到质数的题,大胆\(DFS\),多剪枝就好了

——后记

标签:燕姿,limits,int,题解,质数,zs,bmod,equiv
From: https://www.cnblogs.com/pengchujie/p/17801601.html

相关文章

  • CF1707 题解
    CF1707题解A考场上1h才出思路...弱智了。我们将参加大于当前智商的行为叫做“摆烂”。我们考虑如果现在摆一次,将来某一次不摆,那么现在不摆,将来那次开摆,中间过程的智商会加1。更优。所以一定一摆就摆到底。而且一定会摆到最后一个。所以我们二分从什么时候开摆,看是否能摆到......
  • 题解:洛谷P3745 期末考试(整数三分)
    题解:洛谷P3745期末考试(整数三分)题目传送门题目大意:给出\(n\)个同学期望出成绩的时间限制\(a_i\)和\(m\)个学科公布成绩的初始时间\(t_i\),1个同学每多等一天就产生A的不愉快度。问通过一番操作后最小的不愉快度之和是多少?操作有两种:1.让学科X的发布时间晚1天,学科......
  • P5404 [CTS2019] 重复 题解
    题目链接观察题目,我们发现直接计算是困难的,先构造单个合法的\(T\)分析其性质。为了构造出\(T\),先考虑构造时\(T\)时什么时候会出现不合法的情况,此时\(T\)会有一段和\(S\)相同的前缀,且这段前缀后面跟着的字符比\(S\)所跟的小。为了避免这种情况出现,我们需要在每次添......
  • CSPRO 历届题目与题解
    官方题目链接:http://118.190.20.162/\(\Huge目录\)201609201612201709202104202109202112202203202206202209202303202305202309\(\Huge\text{CSP201609}\)火车购票问题描述请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配。假设一节车厢......
  • AT_abc326_d ABC Puzzle 题解
    AT_abc326_dABCPuzzle题解看题事实上,即使在\(N=5\)的情况下,也只有\(66240\)个网格满足「每行/每列恰好包含一个A、B和C」。——官方题解其实看到这道题,就感觉是搜索,这很显然。但是我们会发现,最最最native的搜索,是\(4^{5\times5}=2^{50}\)的。感觉不大可过,但是......
  • AT_abc326_e Revenge of "The Salary of AtCoder Inc." 题解
    AT_abc326_eRevengeof"TheSalaryofAtCoderInc."题解一道简单的概率论+动态规划题目(然而我赛时没看这道题题意有一个长度为\(n\)的序列\(A\)、一个\(n\)面骰子,掷若干次骰子,如果这一次掷骰子的点数小于等于上一次的点数,则结束。定义这若干次掷骰子的总的结果为,每次......
  • AT_abc326_f Robot Rotation 题解
    AT_abc326_fRobotRotation题解经典问题,以前遇到过一个类似的问题:[ABC082D]FTRobot。建议对比着看一看这两道题,是两种不同的思路。(那一道题不用输出方案,因此可以用bitset优化;而此题需要输出方案,因此需要双向搜索。思路注意到每次只能「左转」和「左转」。所以,偶数次走......
  • AT_abc325_f Sensor Optimization Dilemma 题解
    AT_abc325_fSensorOptimizationDilemma题解Date20231025:修复手滑公式\(\min\)、\(\max\)写反了。动态规划。类似背包问题。朴素算法记\((x,y)\)表示使用\(x\)个(1)传感器、\(y\)个(2)号传感器。设\(f(t,i,j)\)表示覆盖前\(t\)个区间,使用\((i,j)\)传感......
  • AT_abc325_g offence 题解
    AT_abc325_goffence题解一道不难但是需要想一想的区间DP。有一个比较复杂的例子:ooofofxxx,简单的分析可知,一个of后面删除多少,与其前、后都有关,于是考虑区间DP。想到这里,其实问题已经解决一半了。状态设计设\(f(l,r)\)为闭区间\([l,r]\)经过操作之后的最小长度。注......
  • [CSP-S2020] 儒略日 题解
    [CSP-S2020]儒略日今儿终于做掉困扰多年的题目了,其实想好细节也不难。容易发现儒略历和格里高利历的润年判断方式不一样,并且中间有消失的十天,计算起来相当不方便。所以我们可以首先计算出\(-4713.1.1\)~\(1582.10.4\)会经过多少天,可以通过一天一天暴力跳的方法计算出需要\(......