快速质因数分解及素性测试&ABC142D

首先,这个整数的标准分解非常的显然易见对吧:

一般我们要把一个数分解成这个样子我们可以这样写:

 1 #include<cstdio>
 2 int p[105],w[105],k;
 3 void factorize(int n)
 4 {
 5     for(int i=2;i*i<=n;i++)
 6         if(n%i==0)
 7         {
 8             p[++k]=i;
 9             while(n%i==0)
10                 n/=i,w[k]++;
11         }
12     if(n!=1)
13         p[++k]=n,w[k]=1;
14 }
15 int main()
16 {
17     int n;
18     scanf("%d",&n);
19     factorize(n);
20     for(int i=1;i<k;i++)
21         printf("%d^%d*",p[i],w[i]);
22     printf("%d^%d",p[k],w[k]);
23 }

由于是分解质数,而且质数除了2之外都是奇数,所以可以在枚举i的时候每次i+=2

例题:ABC142D(手边没有什么好题了,只是因为最近做到了它2333)

要找互质的公因数,就相当于找最大公因数的最多互质的因数。(这个表述...相信你们能懂

之前写一直T了,于是找了另外一种方法,后面才发现之前的哪里有问题

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<map>
 4 using namespace std;
 5 #define N 100005
 6 #define ll long long
 7 #define MOD 1000000007
 8 ll x,y;
 9 map<ll,bool> vis;
10 ll p[N];
11 int pn;
12 ll gcd(ll a,ll b)
13 {
14     if(b==0) return a;
15     else return gcd(b,a%b);
16 }
17 int main()
18 {
19     scanf("%lld %lld",&x,&y);
20     ll d=gcd(x,y);
21     int ans=1;
22     if(d%2==0) ans++;
23     while(d%2==0)
24         d/=2;
25     for(ll i=3;i*i<=d;i+=2)//写成i<=d/i就可以不开ll 否则不开ll就会乘爆 然后T掉
26         if(d%i==0)
27         {
28             ans++;
29             while(d%i==0)
30                 d/=i;
31         }
32     if(d!=1) ans++;
33     printf("%d\n",ans);
34     return 0;
35 }

就是我注释的那个地方,要注意那样的BUG了

最后采用了这种写法:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<map>
 4 #include<vector>
 5 #include<cmath>
 6 using namespace std;
 7 #define N 100005
 8 #define ll long long
 9 #define MOD 1000000007
10 ll x,y;
11 map<ll,bool> vis;
12 ll p[N];
13 int pn;
14 vector<ll>st;
15 ll gcd(ll a,ll b)
16 {
17     if(b==0) return a;
18     else return gcd(b,a%b);
19 }
20 bool is_prime(ll x)
21 {
22     if(x==1) return 0;
23     if(x==2||x==3) return 1;
24     if(x%6!=1&&x%6!=5) return 0;
25     int s=sqrt(x);
26     for(int i=5;i<=s;i+=6)
27         if(x%i==0||x%(i+2)==0)
28             return 0;
29     return 1;
30 }
31 int solve(ll n)
32 {
33     int ans=1;
34     if(n==1) return 1;
35     ll i=0;
36     while(i<n)
37     {
38         if(is_prime(n))
39         {
40             st.push_back(n);
41             if(vis[n]==0)ans++;
42             vis[n]=1;
43             return ans;
44         }
45         for(int i=2;i<n;i++)
46         {
47             if(n%i==0)
48             {
49                 st.push_back(i);
50                 if(vis[i]==0)ans++;
51                 vis[i]=1;
52                 n/=i;
53                 break;
54             }
55         }
56     }
57     st.push_back(n);
58     if(vis[n]==0)ans++;
59     vis[n]=1;
60     return ans;
61 }
62 int main()
63 {
64     scanf("%lld %lld",&x,&y);
65     ll d=gcd(x,y);
66     printf("%d\n",solve(d));
67     return 0;
68 }

其实感觉和上面的做法差不多,直接看也就能看懂,但是网上据说是$n^{1/4}$的复杂度,那么还是了解一下,也没有什么坏处。(对于这道题来说其实不需要存因数的啦)

关于is_prime的素数判断,还是说一下吧。

如果不加这个判断,那么在$n$变成一个很大的质数的时候,这个算法就会退化到$O(n)$级别。

对于每一个$>=5$的数可以表示为$6x-1$(也相当于$6x+5$),$6x$,$6x+1$,$6x+2$,$6x+3$,$6x+4$,$6x+5$中的一种。

而$6x$,$6x+2=2(3x+1)$,$6x+3=3(x+1)$,$6x+4=2(3x+2)$,都不可能是素数。

所以我们对于一个数n,直接先判断它模$6$是否余$5$或余$1$,不是的话直接返回false

但是是的话也不一定是素数,还要再判断一下。

每个数都能进行质因数分解,所以我们只要判断用它除前面的素数能否除尽就可以了.

$6x+1$,$6x+5$这样的数显然不可能除的尽$2$和$3$,所以我们从$5$开始判断。

下一个除以$7$,按照上面的讨论,下一个为$11$和$13$。

网上有人说,以此类推,可以把步长增加到$6$来加快运行速度。

不知道怎么证明,但是验证了一下是对的。(怎么感觉好水...)



莫名其妙地就干完了这篇博客。

写得好水呀。

嘤嘤嘤我在干什么。

原文地址:https://www.cnblogs.com/lyttt/p/11621727.html

时间: 2024-07-31 14:10:31

快速质因数分解及素性测试&ABC142D的相关文章

浅谈质因数分解

浅谈质因数分解 ->part 1: 算数基本定理: 任何一个大于1的正整数都能唯一分解为有限个质数的乘积,可写作: \[N=\prod_{i=1}^m p_i^ {c_i}\] 其中\(c_i\)都是正整数,\(p_i\)都是质数,且满足\(p_1<p_2<-<p_m\) ->part 2: 分解方法: 试除法 结合质数判定的"试除法"和质数筛选的"\(Eratosthenes\) 筛法",我们可以扫描 \(2-\sqrt N\)的每个

Miller-Rabin 素性测试 与 Pollard Rho 大整数分解

\(\\\) Miller-Rabin 素性测试 考虑如何检验一个数字是否为素数. 经典的试除法复杂度 \(O(\sqrt N)\) 适用于询问 \(N\le 10^{16}\) 的时候. 如果我们要把询问范围加到 \(10^{18}\) ,再多组询问呢? Miller 和 Rabin 建立了Miller-Rabin 质数测试算法. \(\\\) Fermat 测试 首先我们知道费马小定理: \[ a^{p-1}\equiv 1\pmod p \] 当且仅当 \(p\) 为素数时成立. 逆命题是

质因数分解的rho以及miller-rabin

一.前言 质因数分解,是一个在算法竞赛里老生常谈的经典问题.我们在解决许多问题的时候需要用到质因数分解来辅助运算,而且质因数分解牵扯到许许多多经典高效的算法,例如miller-rabin判断素数算法,rho启发式搜索质因数分解算法等.在此文里,我要介绍的就是miller-rabin算法以及rho启发式搜索分解算法. 二.算术基本定理 首先,我们得知道,任意一个大于1的自然数都可以分解为有限个质数的乘积.这里因子均为质数,且为正整数.我们把这样的分解成为N的标准分解式.关于算数基本定理的应用有许多

数论部分第一节:素数与素性测试【详解】

数论部分第一节:素数与素性测试 一个数是素数(也叫质数),当且仅当它的约数只有两个——1和它本身.规定这两个约数不能相同,因此1不是素数.对素数的研究属于数论范畴,你可以看到许多数学家没事就想出一些符合某种性质的素数并称它为某某某素数.整个数论几乎就围绕着整除和素数之类的词转过去转过来.对于写代码的人来说,素数比想像中的更重要,Google一下BigPrime或者big_prime你总会发现大堆大堆用到了素数常量的程序代码.平时没事时可以记一些素数下来以备急用.我会选一些好记的素数,比如4567

米勒-拉宾素性测试学习

之前一直对于这个神奇的素性判定方法感到痴迷而又没有时间去了解.借着学习<信息安全数学基础>将素性这一判定方法学习一遍. 首先证明一下费马小定理. 若p为素数,且gcd(a, p)=1, 则有 a^(p-1) = 1 (mod p) 基于以下定理 若(a, p)=1,{x| (x, p)=1}为模p下的一个完全剩余系,则{ax| (x, p)=1}也为模p下的一个完全剩余系. 又{0, 1, 2, ... p-1}为模p下一个剩余系   因此有, {a*0, a*1, a*2, ... a*(p

米勒-拉宾(MillerRabbin)素性测试算法

首先,在了解米勒-拉宾素性测试之前,我们要先了解费马小定理. 关于费马小定理就不再细说原理和证明了,应用非常广泛. 费马小定理中说  若p是质数  则有 a的(p-1)次方在(mod p)的情况下 恒等于1   数学表达式--->  a^(p-1) ≡ 1 (mod p) 然后我们要注意: p若是质数  则满足费马小定理  但是  满足费马小定理  并不能证明p就是质数 有些数字 满足费马小定理,但是并不是质数  他们叫做伪质数(伪素数的个数是无穷的) 那么 知道了这些  算法就很好理解了 一个

【BZOJ2227】【ZJOI2011】看电影 [组合数学][质因数分解]

看电影 Time Limit: 10 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 到了难得的假期,小白班上组织大家去看电影.但由于假期里看电影的人太多,很难做到让全班看上同一场电影,最后大家在一个偏僻的小胡同里找到了一家电影院.但这家电影院分配座位的方式很特殊,具体方式如下: 1. 电影院的座位共有K个,并被标号为1…K,每个人买完票后会被随机指定一个座位,具体来说是从1…K中等可能的随机选取一个正整数,设其为L.

Codevs 1313 质因数分解

1313 质因数分解 题目描述 Description 已知正整数 n是两个不同的质数的乘积,试求出较大的那个质数 . 输入描述 Input Description 输入只有一行,包含一个正整数 n. 输出描述 Output Description 输出只有一行,包含一个正整数p,即较大的那个质数. 样例输入 Sample Input 21 样例输出 Sample Output 7 #include<iostream> #include<cstdio> #include<cm

HDU 3988 n!质因数分解

Harry Potter and the Hide Story Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2324    Accepted Submission(s): 569 Problem Description iSea is tired of writing the story of Harry Potter, so, l