数学知识—约数

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=p0+...pa 不需要用快速幂再加速了(有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;
}
相关推荐
水云桐程序员2 小时前
C++可以写手机应用吗
开发语言·c++·智能手机
平凡但不平庸的码农2 小时前
Go Slice 详解
算法·golang
炸膛坦客5 小时前
嵌入式 - 数据结构与算法:(1-7)数据结构 - 顺序表和链表的对比
数据结构·链表
Jasmine_llq5 小时前
《B3867 [GESP202309 三级] 小杨的储蓄》
算法·循环遍历·数组累加(模拟)·索引定位·顺序输出
啦啦啦_99995 小时前
案例之 逻辑回归_电信用户流失预测
算法·机器学习·逻辑回归
风筝在晴天搁浅6 小时前
快手/字节 CodeTop LeetCode 415.字符串相加
算法·leetcode
小黄人软件6 小时前
C++读写编辑CSV文件示例源码 用于数据导入导出,比Excel好使
开发语言·c++·excel
郭涤生6 小时前
C++各个版本的性能和安全性总结
开发语言·c++
hoiii1876 小时前
基于栅格法的机器人工作空间划分系统
数据结构·机器人
DragonnAi6 小时前
猫咪如厕检测与分类识别系统系列【十四】 项目结构重新整理-即将开源完整算法
算法·开源