数学知识—约数

20240627 数学知识一 40:32

  1. 类似质数 试除法

    869 求约数

    只要枚举到n/i就够了!!!!

    时间复杂度 O根号n big o notation

    排序52:00

    lnlnn比根号n小 忽略不计 了

    数论题关键算时间复杂度,每一步都算才不会超时!!!

cpp 复制代码
#include<iostream>
	#include<vector>
	#include<algorithm>
	
	using namespace std;
	
	vector<int> get_divisors(int n ){
	    vector<int> res;
	    
	    // 约数 只用看到n/i就够了!!!
	    for(int i = 1; i <= n/i; i ++){
	        if(n %i == 0)
	        {
	            res.push_back(i);
	            // 边界处理,防止重复放 n/i =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<<" ";
	        puts("");
	    }
	    
	    return  0;
	}

记两个不同的公式

870 约数个数

基于算术基本定理

显然:因为排列组合,从α1个p1里选不同个数的p1有0-p1共1+p1种选法

所以约数个数是(α1+1)(α2+1) ......

概率论讲过

N的约数d可以写成:0<=β1<=α1

先分解质因数把a1 a2。。分别分解

map:存<指数的底数pi,质数的幂ai>,然后约数个数就是(幂a1+1)(幂a2+1)(幂+1)= Π(幂+1)

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<unordered_map> //hash表快一点 不map

using namespace std;

typedef long long LL;
const int mod = 1e9+7; //答案需对 109+7取模。

int main(){
    int n;
    cin >> n;
    
    unordered_map<int, int> primes;
    while( n--) {
        int x;
        cin >> x;
        
        // 枚举约数到x/i
        for(int i = 2; i <= x/i; i ++){
            while(x % i == 0){
                x /= i;
                primes[i] ++; //以这个质因数为底的幂 +1
            }
        }
        
        if( x> 1) primes[x] ++; //x是一个比较大的质因数 为啥
        
    }
    
    LL res = 1;
    for(auto prime: primes) res= res*(prime.second +1) % mod;
    cout << res;
    return 0;
}

871 约数之和

类似上面,只不过把约束和表示出来,然后暴力展开

乘积总个数=上面约数个数

如何求t=p^0+...p^a 不需要用快速幂再加速了(有logα算法分治)

总和 求p^0+ ... + p^a;做a次的p*t +1妙啊

Auto+map好用!!

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<unordered_map> //hash表快一点 不map

using namespace std;

typedef long long LL;
const int mod = 1e9+7; //答案需对 109+7取模。

int main(){
    int n;
    cin >> n;
    
    unordered_map<int, int> primes;
    while( n--) {
        int x;
        cin >> x;
        
        // 枚举约数到x/i
        for(int i = 2; i <= x/i; i ++){
            while(x % i == 0){
                x /= i;
                primes[i] ++; //以这个质因数为底的幂 +1
            }
        }
        
        if( x> 1) primes[x] ++; //x是一个比较大的质因数 为啥
        
    }
    
    LL res = 1;
    
    // 870比只改了这里
    for(auto prime: primes) 
    {
        int p = prime.first, a= prime.second;//p底,a指数
        LL t= 1; //总和 求p^0+ ... + p^a;做a次的p*t +1妙啊
        while(a  --) t= (t*p+1) %mod;
        res = res * t % mod;
        
    }
    cout << res;
    return 0;
}

最大公约数------欧几里得算法------辗转相除法 01:19:23

时间复杂度Logn不用更相减损术

性质:

  1. 如果d能整除a(就是a % d =0)而且d整除b,那么d能整除a,b线性组合ax+by

  2. (a,b)=(b, a % b) a和b的最大公约数= b和a模b 的最大公约数

因为a % b= a- (a|b) *b (a模b= a - (a整除b)*b= a -c * b)

所以证明 (a,b) = (b, a-c * b) c=a|b

设a,b公约数是d

那么左边得 d|a且d|b,又因为性质一所以 d| ax +by 这里x=1, y=-c

所以b和a-c*b公约数是d

反过来右边推出 d|b且d|a-cb
所以d|bx+(a-c
b)y,此时y=1,x=c,能推出d|a

所以a b公约数也是d

所以左右所有的公约数集合都相同,所以左边的最大公约数也是右边的 证毕

模板:

cpp 复制代码
#include<iostream>

using namespace std;

// 很常用
int gcd(int a, int b){
    // 如果b=0,返回(b, a%b)的公约数
    // 否则b=0, (a,0)=返回a 不能是0
    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;
}
相关推荐
十年一梦实验室16 分钟前
【C++】相机标定源码笔记- RGB 相机与 ToF 深度传感器校准类
开发语言·c++·笔记·数码相机·计算机视觉
蜉蝣之翼❉25 分钟前
c++ 简单线程池
开发语言·c++
半截詩28 分钟前
力扣Hot100-24两两交换链表中的节点(三指针)
算法
2401_8576363939 分钟前
Scala中的尾递归优化:深入探索与实践
大数据·算法·scala
点云侠1 小时前
matlab 干涉图仿真
开发语言·人工智能·算法·计算机视觉·matlab
夏天的阳光吖1 小时前
每日一题---OJ题:分隔链表
数据结构·链表
2401_857638031 小时前
【深度解析】滑动窗口:目标检测算法的基石
人工智能·算法·目标检测
Czi橙1 小时前
玩玩快速冥(LeetCode50题与70题以及联系斐波那契)
java·算法·快速幂·斐波那契
shuai132_2 小时前
关于std::memory_order_consume
开发语言·c++
Python大数据分析@2 小时前
用Python实现的10种聚类算法汇总
python·算法·聚类