约数的相关算法

试除法求约数

这里可以考虑用set容器,因为set容器是不允许重复的元素出现的 试除法 就是到了i<=n/i的if(x%i==0)ans.insert(i),ans.insert(n/i)就算是他们重复 set容器也是直接忽略了

而且set容器还是有clear的功能的

约数的个数

N=p1^a1*p2^a2*p3^a3…….

那么约数的个数就是ans=(a1+1)*(a2+1)*(a3+1)*……

a1有a1中情况 p1的指数不同 那么N的约数就不同 因此会有a1+1中形式 因为还有1呢

约数的个数 还可以返回set的size这个操作

代码附上:

for(int i = 1; i <= x / i; ++i) {

 ret.insert(i);

  ret.insert(x / i);

}

cout << "约数的个数是: " << ret.size() << '\n';

代码附上:

#include<bits/stdc++.h>
#define int long long 
using namespace std;
 
const int mod = 1e9 + 7;
unordered_map<int, int>Hash;

signed main() {
	int x;
	cin >> x;
	for(int i = 2; i <= x / i; ++i) {
		while(x % i == 0) {
				x /= i;
				Hash[i]++;
		}
	}
	
	if(x > 1)Hash[x]++;//这个要注意 
	
	int ret = 1;
	for(auto i : Hash) {
		ret = ret * (i.second + 1) % mod;
	}
	cout << ret << endl;
	return 0;
}

约数的和

约数的和也是和N=p1^a1*p2^a2*p3^a3…..这有关系的

ans=(p1^0+p1^1+p1^2+….p1^a1)*(p2^1+p2^2+p2^3+…..p2^a2)*……….

这里也是有技巧的

这里a是底数 b是指数while(b--)进行b次操作 t=(t*a+1)

第一次是t=1 第二次t=(a+1)第三次t=(a+1)*a+1就变成a^2+a+1是不是很神奇

  • 最大公约数

辗转相除的原理 其实也是直接可以调用系统函数__gcd 前面是有两个下划线的

最小公倍数直接就是 a*b/__gcd(a,b)就是最小公倍数

但是java里面没有 怎么去写呢?
代码:

后来发现java里面也有自带的求gcd的方法 不过在BigInteger里面 BigInteger的valueof可以进行类型之间的转换 java里面一般用的是long 就可以表示很大的数了

约数的个数的例题:

  • 分析:

数学公式的推导和约数的个数的应用

  • 代码:
    void init(int n) {
            for(int i = 2; i <= n; ++ i ) {
                    if(st[i] == false)primes[++cnt] = i;
                    for(int j = 1; primes[j] <= n / i; ++ j ) {
                            st[i * primes[j]] = true;
                            if(i % primes[j] == 0)break;
                    }
            }
    }
    
    signed main() {
            IOS;
            init(1000000);
            
            int n, ret = 1;
            cin >> n;
            //题目的间接的意思 就是让咱们求 n^2 的阶乘约数的个数 
            for(int i = 2; i <= n; ++ i ) {//枚举的是质数 
                    int x = i, t = 0;
                    if(st[i] == true)continue;
                    while(x <= n) {//看看n的阶乘里面可以分解多少个X 
                            t += n / x;
                            x = x * i;
                    }
                    ret = ret * (1 + 2 * t) % mod;
            }
            cout << ret << endl; 
            return 0;
    }
    
  • 反素数(例题):

  • 分析:

这个题是dfs 和想不到的贪心和数学推导

  • 代码:
    void dfs(int len, int last, int p, int sum ) {//质数数组的长度 上一次用的个数  记录的这个数值  当前约数的个数 
        if(sum > Max || (sum == Max && p < ret)) {
        	ret = p, Max = sum;
    	}
    	if(len == 8 + 1) {
    		return ;
    	}
    	for(int i = 1; i <= last; ++ i ) {
    		p = p * primes[len];//继承 
    		if(p <= n) {
    			dfs(len + 1, i, p, sum * (1 + i));
    		} else return; 
    	}
    }
    signed main() {
    	IOS;
    	cin >> n;
    	dfs(0, 30, 1, 1);
    	cout << ret << endl;
    	return 0;
    }
  • 例题:

题目的大概意思是 给你四个数

a b c d

让你求有多少满足条件的

gcd(x, a) = b

lcm(x, c) = d

分析:

lcm(x, c) = d 可以知道xd的因数 因此可以去枚举d的所有因数 看看有哪些满足条件的

  • 代码:

但是这样的算法不是很完美

分析2:
lcm 枚举质因数 然后暴搜

牛客小白月赛81

C-陶陶学算术_牛客小白月赛81 (nowcoder.com)

java会超时
用的是大整数会超时 后期补一下

  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FindYou.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值