Mathematical knowledge I

Posted by animedls on Sun, 31 Oct 2021 16:52:32 +0100

1, Prime number

Prime number, composite number: all for nature greater than 1.
Prime number: contains only two divisors of 1 and itself.
1. Judging prime number (Trial Division) O(sqrt(n))
When enumerating, you only need to enumerate to sqrt(n), because if i is a factor of X, then x/i is also a factor of X.

#include<iostream>
using namespace std;
bool IsPrime(int x)
{
	if(x<2)
		return false;
	for(int i=2;i<=x/i;i++)//I < = x / I instead of I * I < = x is to prevent data overflow
	{
		if(x%i==0)
			return false;
	}
	return true;
}

2. Decomposition quality factor (Trial Division) O(logn)~O(sqrt(n))
Idea: traverse all the numbers from 2 to X

#include<iostream>
using namespace std;
void devide(int x)
{
	for(int i=2;i<=x/i;i++)//You can enumerate to sqrt(x), because a number has at most one factor greater than sqrt(x)
	{
		if(x%i==0)
		{
			int s=0;
			while(x%i==0)
			{
				x/=i;//i is the decomposed prime factor
				s++;//Index of each prime factor
			}
			cout<<i<<' '<<s<<endl;
		}
	}
	if(x>1)
		cout<<x<<' '<<1<<endl;//The last prime factor greater than sqrt(x) has and only one
}

int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		int x;
		cin>>x;
		devide(x);
		cout<<endl;
	}
	return 0;
}

2, Prime number

1. Prime filter
(1) Ehrlich sieve method O(nloglogn)
Principle: while screening prime numbers, screen out the multiples of all prime numbers. Because the multiples of prime numbers must be composite numbers, there is no need to screen out the multiples of each number one by one.

#include<iostream>
using namespace std;
const int N=1e5;
int prime[N],cnt;//Storage prime
bool st[N];//Judge whether the number is screened out
void getPrime(int n)//Filter all primes from 2~x
{
	for(int i=2;i<=n;i++)
	{
		if(!st[i])
		{
			prime[cnt++]=i;
			for(int j=i+i;j<=n;j+=i)//Sift out multiples of prime numbers
				st[j]=true;
		}
	}
}

(2) Linear sieve
Core: the composite number in 1~n will only be screened out by its minimum prime factor. Use the minimum prime factor of each number to sift it out to ensure that each number will be sifted only once. Starting from the minimum prime number, each number must have a minimum quality factor. If you use the minimum quality factor of each number to screen it, you can ensure that each number will be screened only once.

void getPrime(int n)
{
	for(int i=2;i<=n;i++)
	{
		if(!st[i])
			prime[cnt++]=i;
		for(int j=0;prime[j]<=n/i;j++)
		{
			st[i*prime[j]]=true;
			if(i%prime[j]==0)//prime[j] must be the minimum prime factor of i and i*prime[j]. This step ensures that each number will be screened only once in the end
				break;
		}
	}
}
int main()
{
	int n;
	cin>>n;
	getPrime(n);
	cout<<cnt<<endl;
	return 0;
}

3, Divisor
1. Divisor (Trial Division)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> item;
vector<int> get_divisors(int x)
{
	vector<int> res;
	for(int i=1;i<=x/i;i++)
	{
		{
			if(x%i==0)
			{
				res.push_back(i);
				if(i!=x/i)//Special judgment repeated
					res.push_back(x/i);
			}
		}
	}
	sort(res.begin(),res.end());
	return res;
}
int main()
{
	int n,x;
	scanf("%d",&n);
	while(n--)
	{
		item.clear();//Remember to empty
		scanf("%d",&x);
		item=get_divisors(x);
		for(auto items:item)
			printf("%d ",items);
		printf("\n");
	}
	return 0;
}

2. Find the number of divisors
Formula: (a1+1)*(a2+1)*...*(ai+1), ai is the index of the corresponding quality factor.
For any number n, it can be decomposed into prime factor n=P1^(a1)*P2^(a2)...Pk^(ak), and for any divisor D of N, it can be expressed as d=P1^(b1)*P2^(b2)...Pk^(bk), where 1 < = bi < AI. Therefore, each bi has the method of taking (0~ai) from ai+1, so n will have (a1+1)*(a2+1)*...*(ai+1) divisors in total.

#include<iostream>
#include<unordered_map>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
	int n;
	unordered_map<int,int> primes;//Let the base and index map one by one
	cin>>n;
	while(n--)//Decomposition quality factor
	{
		long long x;
		cin>>x;
		for(int i=2;i<=x/i;i++)
		{
			if(x%i==0)
			{
				while(x%i==0)
				{
					x/=i;
					primes[i]++;//Index of storage factor i
				}
			}
		}
		if(x>1) primes[x]++;
	}
	long long res=1;
	for(auto prime:primes)
		res=res*(prime.second+1)%mod;
	cout<<res<<endl;
	return 0;
}

3. Find the sum of divisors of n numbers
Formula: (P1^0+P1^1+...+P1^ak)*(P2^0+P2^1+...+P2^ak)*...*(Pk^0+P1^1+...+Pk^ak), Pi is the result of decomposing prime factors of all numbers.
Taking this formula apart, we can get multiple (P1^b1*P2^b2*...*Pk^bk) added polynomials, and each term must be a divisor of n.

#include<iostream>
#include<unordered_map>
using namespace std;
const int mod=1e9+7;
typedef long long ll;
int main()
{
	int n;
	unordered_map<int,int> primes;
	cin>>n;
	while(n--)
	{
		ll x;
		cin>>x;
		for(int i=2;i<=x/i;i++)
		{
			if(x%i==0)
			{
				while(x%i==0)
				{
					x/=i;
					primes[i]++;
				}
			}
		}
		if(x>1) primes[x]++;
	}
	ll res=1;
	for(auto prime:primes)
	{
		ll p=prime.first,a=prime.second;
		ll t=1;
		while(a--)
		{
			t=(t*p+1)%mod;//formula
		}
		res=res*t%mod;
	}
	cout<<res<<endl;
	return 0;
}

4. Find the greatest common divisor

#include<iostream>
using namespace std;
int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}

4, Euler function

1. 873. Euler function
φ (n) Find the number of Coprime numbers with N in 1~n.
Coprime, that is, the maximum common divisor of two numbers is only 1, gcd(a,b)=1.
Decompose the prime factor of N: n=p1^(a1)*p2^(a2)*...*pk^(ak)
Formula: φ (n)=n*(1-1/p1)*(1-1/p2)*...*(1-1/pk)

#include<iostream>
using namespace std;
int phi(int x)//Decomposition quality factor + Euler formula
{
	int res=x;
	for(int i=2;i<=x/i;i++)
	{
		if(x%i==0)
		{
			res=res/i*(i-1);//res=res*(1-i/i) because 1/i is rounded, write it in another form
			while(x%i==0)
				x/=i;
		}
	}
	if(x>1) res=res/x*(x-1);
	return res;
}
int main()
{
	int n;
	scanf("%d",&n);
	while(n--)
	{
		int x;
		scanf("%d",&x);
		printf("%d\n",phi(x));
	}
}

2. Finding Euler function by sieve method
Find the sum of Euler functions of each number in 1~n
Principle: using the formula of linear sieve + Euler function

#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int phi[N],prime[N],flag[N],cnt;
ll get_euler(int n)
{
	phi[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!flag[i])
		{
			prime[cnt++]=i;
			phi[i]=i-1;//When i is a prime number, the number coprime with it except itself
		}
		for(int j=0;prime[j]<=n/i;j++)
		{
			flag[i*prime[j]]=1;
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];//prime[j] is the smallest prime factor of I, so the prime factor of i*prime[j] is already in φ (i) Calculated in, just change the value of N
				break;
			}
			//prime[j] is the prime factor of i*prime[j],
			//So phi[i*prime[j]]=i*prime[j]*(1-1/(Pk))*(1-1/prime[j]), and i*(1-1/(Pk))= φ (i),
			//Therefore, phi[i*prime[j]]=phi[i]*prime[j]*(1-1/prime[j])=phi[i](prime[j]-1).
			phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
    ll res=0;
	for(int i=1;i<=n;i++)
		res+=phi[i];
	return res;
}
int main()
{
	int n;
	scanf("%d",&n);
	printf("%lld\n",get_euler(n));
	return 0;
}

Topics: C++ Algorithm