The second training of Lanqiao Cup-Number Theory

Greatest common divisor

Refers to the largest divisor of two or more integers

Prime factorization

Prime factor decomposition method: decompose each number into prime factors separately, and then extract all the common prime factors in each number and multiply, and the product obtained is the greatest common divisor of these numbers.

例如
6=2*3
4=2*2
相同的有2
所以2就是4,6的最大公约数

Toss and divide

Tossing and tossing division: Tossing and tossing division is a method to find the greatest common divisor of two natural numbers, also called Euclidean algorithm.

例如
120 50
120%50=20
50%20=10
20%10=0

10就是12050的最大公约数

Code

int gcd(int a,int b)
{
    
    
	if(a%b==0){
    
    
		return b;
	}
	else{
    
    
		//cout<<b<<" "<<(a%b)<<endl; 
		gcd(b,a%b);
	}
}



#include <bits/stdc++.h>

using namespace std;

int gcd(int a,int b)
{
    
    
	if(a%b==0){
    
    
		return b;
	}
	else{
    
    
		//cout<<b<<" "<<(a%b)<<endl; 
		gcd(b,a%b);
	}
}
int main()
{
    
    
	
	int a=50;
	int b=120;
	cout<<gcd(a,b);
	
	
 } 

I don’t know if you have the same question as me. I thought that the function I wrote can only run if a is greater than b. In fact, it is the same whether a is greater than b or a is less than b

Least common multiple

After knowing the greatest common factor, the least common multiple is very simple

a和b的最大公因数是d
a和b的最小公倍数就为 a*b/d  记住公式就可以了

但是注意一下, a*b有可能会溢出,爆出int的范围,所以更恰当的写法是 a/d*b

By the way, the range of int is about 10 to the 9th power, and
the range of long long is about 10 to the 18th power.

Sometimes choose the right one according to the range given by the title. If you find that a negative number or a very outrageous number is found, it may be the cause of the overflow.

Prime number

A prime number refers to a natural number that has no other factors except 1 and itself among the natural numbers greater than 1.

Ordinary method for finding prime numbers

bool isprime(int n){
    
    
	if(n<=1){
    
    
		return false;
	}
	int sqr=(int)sqrt(n*1.0);
	for(int i=2;i<=sqr;i++){
    
    
		 if(n%i==0){
    
    
		 	return false;
		 }
	}
	return true;
}

Think about why you can optimize the algorithm by finding the root sign

Ehrlich Screening

A multiple of a prime number must not be a prime number

埃氏筛选法的思想:首先将2到n范围内的整数写下来,其中2是最小的素数。将表
中所有的2的倍数划去,表中剩下的最小的数字就是3,他不能被更小的数整除,
所以3是素数。再将表中所有的3的倍数划去……以此类推,如果表中剩余的最小的
数是m,那么m就是素数。然后将表中所有m的倍数划去,像这样反复操作,就能依
次枚举n以内的素数。

Insert picture description here

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int ans[maxn]; //全局变量自动赋值为0 
bool pri[maxn];
int num;
void findprime()
{
    
    
	for(int i=2;i<maxn;i++){
    
    
		if(pri[i]==0){
    
    
			ans[num++]=i;
			for(int j=i+i;j<maxn;j+=i)
			{
    
    
				pri[j]=true;
			}
		}
	} 
}
int main()
{
    
    
	findprime();//注意一定不要忘记调用函数了 
	for(int i=0;i<100;i++){
    
    
		cout<<ans[i]<<" ";
		if(i%10==0){
    
    
			cout<<endl;
		}
	}
	return 0;
}

Linear sieve (just understand)

The core of the linear sieve is to ensure that it is used in the small quality factor sieve every time it is dried. The
linear sieve method-O(n), when n = 1e7, it is basically twice
as fast as the Angstrom sieve method. When n is relatively small At that time, the speed of the two sieving methods is almost the same

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1e6+10;
int n,num;
int ans[maxn];//ans数组用来存放质数
bool p[maxn];//p[i], i为质数则为false否则为true

void find_prime(int n){
    
    
	for(int i=2;i<=n;i++){
    
    
		if(p[i]==false){
    
    
			 ans[num++]=i;
		}
		for(int j=0;j<num&&ans[j]<=n/i;j++){
    
    
			 //对于任意一个合数x,假设pj为x最小质因子,当i==x/pj时,一定会被筛掉
			 p[ans[j]*i]=true;
			 if(i%ans[j]==0){
    
    
			 	break;
		//1.i%pj == 0,因为pj是从小到大枚举的 pj定为i最小质因子,pj也定为pj*i最小质因子
		//2.i%pj != 0, pj定小于i的所有质因子,所以pj也为pj*i最小质因子
			 }
		}
	}
}

Large number operation, high precision

When sometimes the number is very large and even exceeds the longlong range, how can we calculate it? This uses a high-precision algorithm

Here is a digression, python is really fragrant, and it supports large numbers, which means that you have to write a lot of hard C language, and other people's python can directly calculate it.

High-precision addition

#include <iostream>
#include <string>
#include <algorithm> 
#include <vector>
using namespace std;
vector<int> a,b,c;


vector<int> add(vector<int> &a,vector<int> &b){
    
    
  if(a.size()<b.size()){
    
    
   return add(b,a);//一两个数最长的那个为基准
  }
  int t=0;
  
  for(int i=0;i<a.size();i++){
    
    
   t+=a[i];
   if(i<b.size()){
    
    //当b的当前位还有数的时候加b[i]
    t+=b[i];
   }
   c.push_back(t%10);//当前位压入c
   t=t/10;//进位
  }
  if(t){
    
    
   c.push_back(t);//判断最高位是否有进位
   
  } 
  return c;//别忘记返回
  }

int main()
{
    
    
	
 string s1,s2;
 cin>>s1>>s2;
 
 for(int i=s1.length()-1;i>=0;i--){
    
    
 	a.push_back(s1[i]-'0');
 } 
 for(int i=s2.length()-1;i>=0;i--){
    
    
 	b.push_back(s2[i]-'0');
 }	

  c=add(a,b);
  for(int i=c.size()-1;i>=0;i--)
  {
    
    
  	cout<<c[i]; 
  }	
}

High precision subtraction

#include <iostream>
#include <string>
#include <algorithm> 
#include <vector>
using namespace std;
vector<int> a,b,c;
bool cmp(vector<int> a,vector<int> b){
    
     //判断a和b谁大 
	if(a.size()!=b.size()){
    
    
		 return a.size()>b.size();//如果长度不相等,长度大的大 
	}
	else{
    
    
		for(int i=a.size()-1;i>=0;i--){
    
    //注意要从最高位开始比较
			if(a[i]!=b[i]){
    
    
				return a[i]>b[i];//如果长度相等,从最高位往最低为做比较大的大 
			}
		}
		return true;//相等返回真 
	}
	
}
vector<int> sub(vector<int> a,vector<int>b){
    
    
       vector<int> c;
	   for(int i=0,t=0;i<a.size();i++){
    
    //t是借位 
	        t=a[i]-t;//当i小于b的长度时a[i]-b[i]-t 否则a[i]-t 
	        if(i<b.size()){
    
    
	            t=t-b[i];
	        }
	        c.push_back((t+10)%10);//如果t小于0就向高位借一位,t大于0直接存起来。模10就把两种情况写一起 
	        if(t<0){
    
    
	            t=1;
	        }
	        else{
    
    
	            t=0;
	        }
	   }
	   while(c.size()>1&&c.back()==0){
    
    
	       c.pop_back();//消除前导零 
	   }
	   return c;//别忘记返回值
} 

int main()
{
    
    
	
 string s1,s2;
 cin>>s1>>s2;
 
 for(int i=s1.length()-1;i>=0;i--){
    
    
 	a.push_back(s1[i]-'0');
 } 
 for(int i=s2.length()-1;i>=0;i--){
    
    
 	b.push_back(s2[i]-'0');
 }	

   if(cmp(a,b))
   {
    
    
   	c=sub(a,b);
   }
   else{
    
    
   c=sub(b,a);
   }
  for(int i=c.size()-1;i>=0;i--)
  {
    
    
  	cout<<c[i]; 
  }	
}

High-precision multiplication

#include <iostream>
#include <vector>
#include <string>
using namespace std;

vector<int> mul(vector<int> a,int b){
    
    
	vector<int> c;
	int t=0;
	for(int i=0;i<a.size();i++){
    
    
		  t=a[i]*b+t;
		  c.push_back(t%10);
		  t=t/10;
	}
	while(t){
    
    
		c.push_back(t%10);//可能有不止一位进位 
		t=t/10;
	}
	return c;
}

int main()
{
    
    
    string s1;
    vector<int> a,c;
    int b;
    cin>>s1>>b;
   for(int i=s1.length()-1;i>=0;i--)
    {
    
    
    	a.push_back(s1[i]-'0');
	}
    c=mul(a,b);
    for(int i=c.size()-1;i>=0;i--){
    
    
    	cout<<c[i];
	}
    
    return 0;
}

High precision division

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

vector<int> div(vector<int> a,int b,int &r){
    
    
	vector<int> c;
	
	for(int i=a.size()-1;i>=0;i--){
    
    //从高位到低位除以除数 
	         r=r*10+a[i];
	       	 c.push_back(r/b);
	       	 r=r%b;
		   
	}
	reverse(c.begin(),c.end());
	while(c.size()>1&&c.back()==0){
    
    
		c.pop_back();//消除前导零 
	}
	return c;
}

int main()
{
    
    
    string s1;
    vector<int> a,c;
    int b,r=0;
    cin>>s1>>b;
   for(int i=s1.length()-1;i>=0;i--)
    {
    
    
    	a.push_back(s1[i]-'0');
	}
    c=div(a,b,r);
    for(int i=c.size()-1;i>=0;i--){
    
    
    	cout<<c[i];
	}
    cout<<endl<<r;//输出余数 
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44866153/article/details/112425863