约数的相关算法

试除法求约数

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

约数的相关算法_第1张图片

而且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
#define int long long 
using namespace std;
 
const int mod = 1e9 + 7;
unordered_mapHash;

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)*……….

这里也是有技巧的

约数的相关算法_第2张图片

这里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 就可以表示很大的数了

约数的个数的例题:

  • 分析:

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

约数的相关算法_第3张图片

  • 代码:
    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;
    }
    
  • 反素数(例题):

约数的相关算法_第4张图片

  • 分析:

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

约数的相关算法_第5张图片

  • 代码:
    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的所有因数 看看有哪些满足条件的

  • 代码:

约数的相关算法_第6张图片

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

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

约数的相关算法_第7张图片

牛客小白月赛81

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

约数的相关算法_第8张图片

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

你可能感兴趣的:(算法,数学知识,算法)