870. 约数个数 and 871. 约数之和

给定 n 个正整数 ai,请你输出这些数的乘积的约数个数,答案对 1e9+7 取模。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个整数 ai。

输出格式

输出一个整数,表示所给正整数的乘积的约数个数,答案需对 1e9+7取模。

数据范围

1≤n≤100,
1≤ai≤2×109

输入样例:

3
2
6
8

输出样例:

12

//筛法求约数个数
int cnt;
int a[N];//记录最小质因子的个数
int d[N];//记录i的约数个数
void get(int n) {
	int visits[N];
	cnt = 0;
	d[1] = 1;
	memset(visits, 0, sizeof(visits));
	memset(prime, 0, sizeof(prime));
	memset(a, 0, sizeof(a));
	memset(d, 0, sizeof(d));
	//线性筛法
	for (int i = 2; i <= n; i++) {
		
		if (!visits[i]) {
			prime[++cnt] = i;
			a[i] = 1;
			d[i] = 2;
		}
		for (int j = 1; j <= cnt; j++) {
			int m = prime[j] * i;
			if (m > n) break;
			visits[m] = 1;
			if (i % prime[j] == 0) {  // prime[j]*i的最小质因子都是 prime[j]
				a[m] = a[i] + 1;//a记录最小质因子 它比a[i]多了一个prime[j]
				d[m] = d[i] / a[m] * (a[m] + 1);
				break;
			}
			else { 
				a[m] = 1;// i
				d[m] = d[i] * 2;
			}
		}
	}
}

约数和

给定 n 个正整数 ai,请你输出这些数的乘积的约数之和,答案对 109+7 取模。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个整数 ai。

输出格式

输出一个整数,表示所给正整数的乘积的约数之和,答案需对 109+7 取模。

数据范围

1≤n≤100,
1≤ai≤2×109

输入样例:

3
2
6
8

输出样例:

252

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3;
int prime[N + 1];
bool visit[N + 1];
int vis[N + 1];
//线性筛法
int prime_visit(int n) {
	int cnt = 0;
	memset(vis, 0, sizeof(vis));
	memset(prime, 0, sizeof(prime));
	for (int i = 2; i <= n; i++) {
		if (!vis[i]) vis[i] = i, prime[cnt++] = i;
		for (int j = 0; j < cnt; j++) {
			if (prime[j] * i > n) break;
			visit[prime[j] * i] = prime[j];// 记录最小的质因数 
			if (i % prime[j] == 0) break;
		}
	}
	return cnt;
}
// 试除法分解质因数 (只能对一个数做因式分解)
int c[40]; // 记录第i个因数的个数
int p[40];//p[1]是最小因数 p[ ]记录因数 
int factor(int n) {
	int m = 0;
	for (int i = 2; i <= sqrt(n); i++) {
		if (n % i == 0) {
			p[++m] = i, c[m] = 0;
			while (n % i == 0) n /= i, c[m]++;
		}
	}
	if (n > 1) p[++m] = n, c[m] = 1;
	return m;
}
 
//筛法求约数个数
int cnt;
int a[N];//记录最小质因子的个数
int d[N];//记录i的约数个数
void get(int n) {
	int visits[N];
	cnt = 0;
	d[1] = 1;
	memset(visits, 0, sizeof(visits));
	memset(prime, 0, sizeof(prime));
	memset(a, 0, sizeof(a));
	memset(d, 0, sizeof(d));
	//线性筛法
	for (int i = 2; i <= n; i++) {
		
		if (!visits[i]) {
			prime[++cnt] = i;
			a[i] = 1;
			d[i] = 2;
		}
		for (int j = 1; j <= cnt; j++) {
			int m = prime[j] * i;
			if (m > n) break;
			visits[m] = 1;
			if (i % prime[j] == 0) {  // prime[j]*i的最小质因子都是 prime[j]
				a[m] = a[i] + 1;//a记录最小质因子 它比a[i]多了一个prime[j]
				d[m] = d[i] / a[m] * (a[m] + 1);
				break;
			}
			else { 
				a[m] = 1;// i
				d[m] = d[i] * 2;
			}
		}
	}
}
int g[N]; //1 + p^1 + ```+p^k
int f[N];// 第i个的约数和
void get_f(int n) {
	g[1] = 1;
	f[1] = 1;
	memset(visit, false, sizeof(visit));
	memset(prime, 0, sizeof(prime));
	int cnt = 0;
	for (int i = 2; i <= n; i++) {
		if (!visit[i])
		{
			prime[++cnt] = i;
			g[i] = 1 + i;
			f[i] = i + 1;
		}
		for (int j = 1; j <= cnt; j++) {
			int m = i * prime[j];
			if (m > n) { break; }
			visit[m] = true;
			if (i % prime[j] == 0) { // prime[j]是最小共因数
				g[m] = g[i]*prime[j] +1;
				f[m] = f[i] / g[i] * g[m];
				break;
			}
			else {
				g[m] = prime[j] + 1;
				f[m] = f[i] * g[m];
			}
		}
	}
}
int main() {
	get(30);
	cout << d[10] << endl;
	get_f(30);
	cout << f[12];
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zhi6fui/article/details/128641768
今日推荐