Number Theory
Determining Prime Numbers: Trial Division
In an integer greater than 1, if it only contains two divisors of 1 and itself, it is called a prime number/prime number It
must be O(sqrt(n))
Not recommended:
i*i<n There is an overflow risk
i<n /i must not overflow
i<sqrt(n) function is called every time
Decomposing Prime Factors: Trial Division
Not necessarily O(sqrt(n))
Best O(logn), worst O(sqrt(n))
According to the Fundamental Theorem of Arithmetic, every positive integer can be represented in a unique way, regardless of the order of arrangement to be the product of its prime factors.
n=p1a1 x p2a2 x p3a3 x…… x pnan
For example, a number 16 first finds the prime factor of 2 when decomposing, and then because 16/2 can still be /2, it will generate a power on the prime factor of 2
Unoptimized version: find the divisible factor from 2~n and calculate the power.
Dissatisfied with this unoptimized version in advance
There is a property here: n contains at most one factor greater than sqrt(n).
The proof is by contradiction: if there are two factors greater than sqrt(n), the multiplication will be greater than n, contradicting. So we find that there is at most one factor greater than sqrt
(n), and optimize it. Consider first that the code is smaller than sqrt(n), and the judgment of the code and the prime number is similar.
Finally, if n is still > 1, it means that there is a unique prime factor greater than sqrt(n) , and the output can be done.
#include <iostream>
void find(int n){
int i;
for(i=2;i<=n/i;i++){
int s=0;
while(n%i==0){
n/=i;
s++;
}
if(s>0)printf("%d %d\n",i,s);
}
if(n>1)printf("%d %d\n",n,1);//大于sqrt(n)的唯一质因子
}
int main(){
int n;
scanf("%d",&n);
while(n--){
int num;
scanf("%d",&num);
find(num);
puts("");
}
return 0;
}
Prime number
1. The most common sieve method O(nlogn)
Sieve out the multiples of all numbers in turn, leaving n/n that is a prime number nlnn
n (n/2+n/+...+n/n)
Prime Number Theorem:
There are n/lnn prime numbers from 1 to n
#include <iostream>
const int N=1e6+100;
bool st[N];
int prim[N];
int cnt;
int n;
void get_primes2(){
for(int i=2;i<=n;i++){
if(!st[i]) primes[cnt++]=i;//把素数存起来
for(int j=i;j<=n;j+=i){
//不管是合数还是质数,都用来筛掉后面它的倍数
st[j]=true;
}
}
}
int main(){
scanf("%d",&n);
get_prim();
printf("%d",cnt);
return 0;
}
2. Eh's sieve method O(nloglogn)
Sieve all the multiples of prime numbers in turn, leaving all prime numbers nlnn/lnn=n
void get_primes1(){
for(int i=2;i<=n;i++){
if(!st[i]){
primes[cnt++]=i;
for(int j=i;j<=n;j+=i) st[j]=true;//可以用质数就把所有的合数都筛掉;
}
}
}
3.3. Linear sieve method O(n)
Core: composite numbers will only be sieved by the smallest prime factor, and each number will only be sieved once, so it is linear
void get_primes(){
//外层从2~n迭代,因为这毕竟算的是1~n中质数的个数,而不是某个数是不是质数的判定
for(int i=2;i<=n;i++){
if(!st[i]) primes[cnt++]=i;
for(int j=0;primes[j]<=n/i;j++){
//primes[j]<=n/i:变形一下得到——primes[j]*i<=n,把大于n的合数都筛了就
//没啥意义了
st[primes[j]*i]=true;//用最小质因子去筛合数
//1)当i%primes[j]!=0时,说明此时遍历到的primes[j]不是i的质因子,那么只可能是此时的primes[j]<i的
//最小质因子,所以primes[j]*i的最小质因子就是primes[j];
//2)当有i%primes[j]==0时,说明i的最小质因子是primes[j],因此primes[j]*i的最小质因子也就应该是
//prime[j],之后接着用st[primes[j+1]*i]=true去筛合数时,就不是用最小质因子去更新了,因为i有最小
//质因子primes[j]<primes[j+1],此时的primes[j+1]不是primes[j+1]*i的最小质因子,此时就应该
//退出循环,避免之后重复进行筛选。
if(i%primes[j]==0) break;
}
}
}
approximation
Finding Divisors: Trial Division
d is a number sub-number, n/d is also a number sub-number, you can only choose the smaller one when enumerating
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void find(int n){
vector<int>a;
for(int i=1;i<=n/i;i++){
if(n%i==0){
a.push_back(i);
if(n/i!=i)a.push_back(n/i);
}
}
sort(a.begin(),a.end());
for(auto t:a){
cout<<t<<' ';
}
}
int main(){
int n;
scanf("%d",&n);
while(n--){
int num;
scanf("%d",&num);
find(num);
puts("");
}
return 0;
}
find the number
At the same time, you can find the number of multiples and the number
of divisors:
Number of multiples: = about 1500 with the largest number in the range of
nlogn ints
find sum of divisors
#include <iostream>
#include <unordered_map>
using namespace std;
const int mod=1e9+7;
typedef long long LL;
int main(){
int n;
scanf("%d",&n);
unordered_map<int, int> hash;
while(n--){
int num;
scanf("%d",&num);
for(int i=2;i<=num/i;i++){
while(num%i==0){
num/=i;
hash[i]++;
}
}
if(num>1)hash[num]++;
}
LL ans=1;
for(auto t:hash){
int p=t.first, a=t.second; a=t.second;
LL pt=1;
while(a--){
pt=(pt*p+1)%mod;
}
ans=ans*pt%mod;
}
printf("%lld",ans);
return 0;
}
Finding the greatest common divisor: Euclidean algorithm O(logn)
Also known as tossing and dividing
If d can divide a, d can divide b,
then d can divide a+b, d can also divide ax+by
Greatest common divisor gcd(a,b)=gcd(b,a mod b)
#include <iostream>
using namespace std;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
int n;
scanf("%d",&n);
while(n--){
int a,b;
scanf("%d%d",&a,&b);
int ans=gcd(a,b);
printf("%d\n",ans);
}
return 0;
}
Euler function
The bottleneck is in decomposing the prime factors, and the time complexity of decomposing the prime factors is O(sqrt(n))
The number of numbers from 1 to n that are relatively prime to n is relatively
prime : that is, the two numbers do not contain a common prime factor
. Count is irrelevant
Proof:
Find the Euler function
#include <iostream>
using namespace std;
int main(){
int n;
scanf("%d",&n);
while(n--){
int x;
scanf("%d",&x);
int res=x;
for(int i=2;i<=x/i;i++){
if(x%i==0){
res=res/i*(i-1);
while(x%i==0){
x/=i;
}
}
}
if(x>1)res=res/x*(x-1);
printf("%d\n",res);
}
return 0;
}
Sieve method to find Euler function
#include <iostream>
using namespace std;
const int N=1e6+100;
typedef long long LL;
int prime[N],cnt;
int phi[N];
bool st[N];
int n;
void get_euler(){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!st[i]){
prime[cnt++]=i;
phi[i]=i-1;
}
for(int j=0;prime[j]<=n/i;j++){
st[i*prime[j]]=true;
if(i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}else{
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
LL ans=0;
for(int i=1;i<=n;i++){
ans+=phi[i];
}
printf("%lld",ans);
}
int main(){
scanf("%d",&n);
get_euler();
return 0;
}
Supplement: Euler's Theorem
Proof:
Special case:
p is a prime number