acwing数学知识

数学知识板子

1.质数

试除法判定质数

分解质因数

筛质数

模板:

//质数的判定 —试除法 
bool Is_prime(int n){
	if(n<2) return false;
	for(int i=2;i<=n/i;i++)
	    if(n%i==0)
	        return false;
	
	return true;
}


//分解质因数 —试除法 
void divide(int n){
	// 性质:n中最多只包含一个大于 sqrt(n) 的质因子
	for(int i=2;i<=n/i;i++)
		if(n%i==0){  // i 一定是质数 
			int s=0;
			while(n%i==0){
				n/=i;
				s++;
			}
			printf("%d %d",i,s);
		}
	
	
	if(n>1) printf("%d %d\n",n,i);
	puts("");
}


//筛质数个数 --埃氏筛法 
void get_primes(int n){
	for(int i=2;i<=n;i++) //从2开始每次留下的数就是质数
		if(!st[i]){
			primes[cnt++]=n;
			for(int j=i+i;j<=n;j+=i) st[j]=true;
			//每次都只把质数的倍数删掉即可
		}
		
}
//---线性筛法求个数 :n只会被最小质因子筛掉 
void get_prime(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[prime[j]*i]=true;
			if(i%prime[j]==0) break;  //核心只被最小质因子筛一次--->线性 -->所以避免了"重复筛"
			                 //i%pirme[j]==0 pj一定是i的最小质因子.pj一定是pj*i的最小质因子  break;
			                 //i%prime[j]!=0 pj一定小于i的所有质因子,pj也一定是pj*i的最小质因子
		}
	}
	
} 


 
 

2.约数


试除法求约数

在这里插入图片描述

输入样例:

2
6
8

输出样例:

1 2 3 6
1 2 4 8

模板:

//试除法求所有约数
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;

vector<int> get_divisors(int n){
	vector<int> res;
	
	for(int i=1;i<=n/i;i++)
		if(n%i==0){
			res.push_back(i);
			if(i!=n/i) res.push_back(n/i);  
		}
	
	sort(res.begin(),res.end());
	
	return res;
}

int main(){
	int n;
	cin>>n;
	
	while(n--){
		int x;
		cin>>x;
		auto res=get_divisors(x);
		for(auto t : res) cout<<t<<" ";
		cout<<endl;
	}
	return 0;
} 

 


约数个数

在这里插入图片描述
在这里插入图片描述

输入样例:

3
2
6
8

输出样例:

12

模板:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;

int main(){
	int n;
	cin>>n;
	
	unordered_map<int,int> primes;
	while(n--){
		int x;
		cin>>x;
		
		for(int i=2;i<=x/i;i++)    //一直除质因数 2 3 5 7 11 ... 最多室友一个大于 sqrt(n) 的质因子 
		    while(x%i==0){
		    	x/=i;
		    	primes[i]++;
			}
		
		if(x>1) primes[x]++;   //大于sqrt(n) 的质因子和 可能本身是质因子的可能 ++ 
	}
	
	LL res=1;
	for(auto prime : primes) res=res * (prime.second+1)%mod;
	
	cout<<res<<endl;
	
	return 0; 
}

 

约数之和

在这里插入图片描述
在这里插入图片描述

输入样例:

3
2
6
8

输出样例:

252

模板:

//约数之和
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<unordered_map>
using namespace std;
const int mod = 1e9+9;
typedef long long LL;

int main(){
	int n;
	cin>>n;
	
	unordered_map<int,int>primes;
	while(n--){
		int x;
		cin>>x;
		
		for(int i=2;i<=x/i;i++){
			while(x%i==0){
				x/=i;
				primes[i]++;
			}
		}
		if(x>1) primes[x]++;
	}
	
	LL res=1;
	for(auto prime : primes){
		int p=prime.first,a=prime.second;
		LL t=1;
		while(a--) t=(t*p+1)%mod;  //------>数学 
		res=res*t%mod;
	}
	
	cout<<res<<endl;
	
	return 0;
} 

 

最大公约数(欧几里得算法)

输入样例:

2
3 6
4 6

输出样例:

3
2

模板:

//最大公约数 
//欧几里得算法   (a,b)=(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);
		printf("%d\n",gcd(a,b));
	}
	
	return 0;
}

 
 

3.欧拉函数


欧拉函数

在这里插入图片描述

输入样例:

3
3
6
8

输出样例:

2
2
4

模板:

//欧拉函数 
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int main(){
	int a;
	cin>>a;
	
	int res=a;
	for(int i=2;i<=a/i;i++)
		if(a%i==0)
		{
			res=res/i*(i-1);
			while(a%i==0) a/=i;
		}
	
	if(a>1) res=res/a*(a-1);
	
	cout<<res<<endl;
	
	return 0;
} 

 

筛法求欧拉函数

在这里插入图片描述
思路:

线性筛法求欧拉函数
1.当 i 为质数时: i 的欧拉函数为 i - 1
2.当 i % pj == 0 ,pj仅仅只是在N种增加了质因数的指数,在欧拉公式可以看出φ(i * pj) = pj * φ(i)。
3.当 i % pj != 0 ,pj在N中增加了一项质因数, 欧拉函数同加一项得φ(i * pj) = φ(i) * pj * (1 - 1/pj) 化简后得 φ(i * pj) = φ(i) * (pj - 1)

输入样例:

6

输出样例:

12

模板:

//线性筛法求欧拉函数
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;

int primes[N],cnt;
int phi[N];
bool st[N];

LL get_eulers(int n){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!st[i]){
			primes[cnt++]=i;
			phi[i]=i-1;  //本身是质数 那么互质的个数是 i-1
		}
		for(int j=0;primes[j]<=n/i;j++){
			st[primes[j]*i] =true;
			if(i%primes[j]==0){  //只是指数增加不影响结果 
				phi[primes[j]*i]=phi[i]*primes[j];
				break;
			}
			// primes[j]中不包含 i 的质因数 
			phi[primes[j]*i]=phi[i]*(primes[j]-1);
		}
	}
	LL res=0;
	for(int i=1;i<=n;i++) res+=phi[i];
	return res;
}

int main(){
	int n;
	cin>>n;
	
	cout<<get_eulers(n)<<endl;
	
	return 0;
}

 
 

4.快速幂


快速幂

在这里插入图片描述

输入样例:

2
3 2 5
4 3 9

输出样例:

4
1

模板:

//快速幂
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;


LL qmi(int a, int b, int p)
{
    LL res = 1 % p;
    while (b)
    {
        if (b & 1) res = res * a % p;
        a = a * (LL)a % p;
        b >>= 1;
    }
    return res;
}


int main()
{
    int n;
    scanf("%d", &n);
    while (n -- )
    {
        int a, b, p;
        scanf("%d%d%d", &a, &b, &p);
        //a ^ b % p = ((a % p)^b) % p
        printf("%lld\n", qmi(a % p, b, p));
    }

    return 0;
}

 

快速幂求逆元

在这里插入图片描述
思路:

逆元同余方程: a/b ≡ a * x( mod p) -> b * x ≡ 1(mod p) (即 x 为所求得逆元)
费马小定理: b^(p-1) ≡ 1(mod p) -> b * b ^(p-2) ≡ 1(modp) (当p为质数)
即当 p 为 质数时 x = b^(p-2)为所求得逆元 -> 快速幂

b 和 p成倍数一定无解

样例输入

3
4 3
8 5
6 3

样例输出:

1
2
impossible

代码模板:

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;


LL qmi(int a, int b, int p)
{
    LL res = 1;
    while (b)
    {
        if (b & 1) res = res * a % p;
        a = a * (LL)a % p;
        b >>= 1;
    }
    return res;
}


int main()
{
    int n;
    scanf("%d", &n);
    while (n -- )
    {
        int a, p;
        scanf("%d%d", &a, &p);
        if (a % p == 0) puts("impossible"); //p = 2 特判
        else printf("%lld\n", qmi(a, p - 2, p));
    }

    return 0;
}

 
 

5.扩展欧几里得算法


扩展欧几里得算法

在这里插入图片描述

输入样例:

2
4 6
8 18

输出样例:

1 1
2 1

模板:

//裴蜀定理 
//扩展欧几里得算法
#include<iostream>
#include<algorithm>
using namespace std;
//递推--- 
//推导过程 
//ax0+by0=gcd(a,b)=gcd(b,a%b)=d(最大公约数)  ax0 + by0
//gcd(b,a%b)=by1+(a%b)x1= by1+(a-|a/b|*b)x1= ax1 + b(y1-a/b*x1)=d
//x0=x1   y0=y1-a/b*x1
int exgcd(int a,int b,int &x,int &y)
{
	if(!b)
	{
		x=1,y=0;
		return a;
	}
	int d=exgcd(b,a%b,y,x);
	y-=a/b*x;   //<---ax + b(y-a/b*x)=d 
	cout<<"a="<<a<<" "<<"b="<<b<<endl;
	cout<<"x="<<x<<" "<<"y="<<y<<endl;
	return d;  //这里返回得是最大公约数
}
int main(){
	int n;
	scanf("%d",&n);
	
	while(n--){
		int a,b,x,y;
		scanf("%d %d",&a,&b);
		
		exgcd(a,b,x,y);
		
		printf("%d %d\n",x,y);
		
	}
	return 0;
} 

 

线性同余方程

在这里插入图片描述


 
 

6.中国剩余定理


表达整数的奇怪方式

在这里插入图片描述

输入样例:

2
8 7
11 9

输出样例:

31

模板:



 
 

7.高斯消元


高斯消元解线性方程组

在这里插入图片描述

输入样例:

3
1.00 2.00 -1.00 -6.00
2.00 1.00 -3.00 -9.00
-1.00 -1.00 2.00 7.00

输出样例:

1.00
-2.00
3.00

模板:

//高斯消元解线性方程组
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

const int N = 110;
const double eps = -1e-6;
int n;
double a[N][N];

void out(){
	for(int i=0;i<n;i++){
		for(int j=0;j<=n;j++) printf("%10.2lf",a[i][j]);
		puts("");
	}
	puts("");
}

int gauss(){
	int c,r;  //c表示列  r表示行 
	
	for(int c=0,r=0;c<n;c++){
		int t=r;
		for(int i=r;i<n;i++)
		    if(fabs(a[i][c])>fabs(a[t][c]))  //找到最大得 c 
		        t=i;
		        
		if(fabs(a[t][c])<eps) continue;
		
		for(int i=c;i<=n;i++) swap(a[t][i],a[r][i]); //换到最上面 
		for(int i=n;i>=c;i--) a[r][i]/=a[r][c];   //将该行第一个数变成 1
		for(int i=r+1;i<n;i++)  //将下面所有行得第 c 变成 0 
		    if(fabs(a[i][c])>eps)
		        for(int j=n;j>=c;j--)
		            a[i][j]-=a[r][j]*a[i][c];
		            
		r++;
	}
	if(r<n)
	{
		for(int i=r;i<n;i++)
		    if(fabs(a[i][n])>eps)
		        return 2;//无解
		return 1;//有无穷多组解 
	}
	for(int i=n-1;i>=0;i--) //倒出唯一解 
	    for(int j=i+1;j<n;j++)
	        a[i][n]-=a[i][j]*a[j][n];
	
	
	return 0;//有唯一解 
}

int main(){
	cin>>n;
	
	for(int i=0;i<n;i++)
	    for(int j=0;j<n+1;j++)
	        cin>>a[i][j];
	        
	int t=gauss();
	
	if(t==0){
		for(int i=0;i<n;i++) printf("%.2lf\n",a[i][n]);
	}
	else if(t==1) puts("Infinite group solution");
	else puts("No solution");
	
	return 0;
} 

//fabs()对 double 取绝对值 

高斯消元解异或线性方程组


 
 

8.求组合数


求组合数I

在这里插入图片描述

输入样例:

3
3 1
5 3
2 2

输出样例:

3
10
1

模板:

//求组合数I  
//递推式 : C(a)\(b) = C(a-1)\(b) + C(a-1)\(b-1) 
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 2010,mod = 1e9+7;

int c[N][N];

void init(){
	for(int i=0;i<N;i++)
	    for(int j=0;j<=i;j++)
	        if(!j) c[i][j]=1;
	        else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}

int main(){
	init();
	
	int n;
	scanf("%d",&n);
	while(n--){
		int a,b;
		scanf("%d%d",&a,&b);
		printf("%d\n",c[a][b]);
	}
	return 0;
} 

 

求组合数II

在这里插入图片描述
思路

定义出发
C a b = a ! ( b − a ) !   b ! C_{a}^{b}=\frac{a!}{(b-a)!\ b!} Cab=(ba)! b!a!

输入样例:

3
3 1
5 3
2 2

输出样例:

3
10
1

模板:

//求组合数II
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int N = 100010,mod = 1e9+7;

int fact[N],infact[N];  //阶乘 

int qmi(int a,int k,int p){
	int res=1;
	while(k){
		if(k&1) res=(LL)res*a%p;
		a=(LL)a*a%p;
		k>>=1;
	}
	return res;
}

int main(){
	fact[0]=infact[0]=1;
	for(int i=1;i<N;i++){
		fact[i]=(LL)fact[i-1]*i%mod;
		infact[i]=(LL)infact[i-1]*qmi(i,mod-2,mod)%mod;
	}
	
	int n;
	scanf("%d",&n);
	while(n--){
		int a,b;
		scanf("%d%d",&a,&b);
		printf("%d\n",(LL)fact[a]*infact[b]%mod*infact[a-b]%mod);
	}
	
	return 0;
} 

 

求组合数III

在这里插入图片描述
思路:

卢卡斯定理: C m n ≡ C m / p n / p ∗ C m   m o d   p n   m o d   p ( m o d   p ) C_{m}^{n}≡C_{m/p}^{n/p} * C_{m\ mod\ p}^{n\ mod\ p} (mod \ p) CmnCm/pn/pCm mod pn mod p(mod p)

输入样例:

3
5 3 7
3 1 5
6 4 13

输出样例:

3 3 2

模板:

//求组合数III
//卢卡斯定理 
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
int p;

int qmi(int a,int k){ //快速幂求乘法逆元 
	int res=1;
	while(k){
		if(k&1)res = (LL)res*a%p;
		a=(LL)a*a%p;
		k>>=1;
	}
	return res;
}

int C(int a,int b){  //阶乘 
	int res=1;
	for(int i=1,j=a;i<=b;i++,j--){
		res=(LL)res*j%p;
		res=(LL)res*qmi(i,p-2)%p;
	}
	return res;
}

int lucas(LL a,LL b){  //卢卡斯定理 
	if(a<p && b<p) return C(a,b);
	return (LL)C(a%p,b%p)*lucas(a/p,b/p)%p;
}

int main(){
	int n;
	cin>>n;
	
	while(n--){
		LL a,b;
		cin>>a>>b>>p;
		cout<<lucas(a,b)<<endl; 
	}
	
	return 0;
}

满足条件的01序列

在这里插入图片描述
思路

卡特兰数 f ( n ) = C 2 n n − C 2 n n − 1 = C 2 n n n + 1 f(n) =C_{2n}^{n} - C_{2n}^{n-1} = \frac{C_{2n}^{n}}{n + 1} f(n)=C2nnC2nn1=n+1C2nn

输入样例:

3

输出样例:

5

模板:

//满足条件的 01 序列 
//卡特兰数
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;

const int mod = 1e9 +7;

int qmi(int a,int k,int p){
	int res=1;
	
	while(k){
		if(k&1) res=(LL)res*a%p;
		a=(LL)a*a%p;
		k>>=1;
	}
	return res;
}

int main(){
	int n;
	cin>>n;
	
	int a=2*n,b=n;
	int res=1;
	
	//定义出发
	for(int i=a;i>a-b;i--) res=(LL)res*i%mod; 
	for(int i=1;i<=b;i++) res=(LL)res*qmi(i,mod-2,mod)%mod;
	
	res=(LL)res*qmi(n+1,mod-2,mod)%mod;
	
	cout<<res<<endl;
	
	return 0;
}

 
 

9.容斥原理


能被整除的数

在这里插入图片描述

输入样例:

10 2
2 3

输出样例:

7

模板:

//容斥原理
//能被整除的数
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int N = 100010;
int n,m;
int p[N];

int main(){
	cin>>n>>m;
	for(int i=0;i<m;i++) cin>>p[i];
	
	int res=0;
	for(int i=1;i<1<<m;i++){ //  枚举所有集合的情况可以用位运算解决 
		int t=1,cnt=0;  //t  为所有质数的乘积  cnt 当前选法里面有几个集合 
		for(int j=0;j<m;j++)
		    if(i>>j&1){
		    	cnt++;
		    	if((LL)t*p[j]>n){
		    		t=-1;
		    		break;
				}
				//cout<<"P[j]="<<p[j]<<" ";
				t*=p[j];
			}
		//cout<<endl;
		if(t!=-1){
			if(cnt%2) res+=n/t;
			else res-=n/t;
		}
	}
	cout<<res<<endl;
	return 0;
} 

 
 

10.博弈论


NIM游戏

在这里插入图片描述

输入样例:

2
2 3

输出样例:

Yes

模板:

//NIM游戏

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

int main(){
	int n;
	int res=0;
	
	scanf("%d",&n);
	while(n--){
		int x;
		scanf("%d",&x);
		res^=x;
		//cout<<"res="<<res<<endl;
	}
	
	if(res) puts("Yes");
	else puts("No");
	
	return 0;
} 

 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值