题目描述
输入n个整数,依次输出每个数的约数的个数
输入描述:
输入的第一行为N,即数组的个数(N<=1000)
接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000)
当N=0时输入结束。
输出描述:
可能有多组输入数据,对于每组输入数据,
输出N行,其中每一行对应上面的一个数的约数的个数。
示例1
输入
复制
5
1 3 4 6 12
输出
复制
1
2
3
4
6
筛法解释: https://blog.csdn.net/controlbear/article/details/77527115
一般的方法会超时,找到一个约数个数定理,约数个数定理可以计算出一个数约数的个数
假设要求的数是m
m=(p1)(x1)*(p2)(x2)(p3)^(x3)……
其中p1,p2,p3…是质数(素数),x1,x2,x3…是它们的指数
则m的约数的个数是(x1+1)(x2+1)(x3+1)……
例如24=(2^3) * (3^1)—分解成质因子的形式
所以其约数的个数为(3+1)(1+1)=8个
突然发现题目的数据太大,这个数组没法开到那么大
代码还是贴在这里,碰到数据小的就可以用这个代码了,后面还有求约数和的问题
#include <stdio.h>
typedef long long ll;
const ll N = 1e5+5;
ll prim[N]; // 表示第N个素数
ll num[N]; // 表示N的最小因子的个数
ll d[N]; // 表示N的因子的个数
// 打表 求1到n每个数的约数个数
void getNum() {
ll mark[N] = {0};
int cnt = 0; // 记录第几个素数
d[1] = 1;
for (int i = 2; i < N; i++) {
if (mark[i] == 0) {
prim[cnt++] = i;
d[i] = 2;
num[i] = 1;
}
for (int j = 0; j < cnt && i*prim[j] < N; j++) {
mark[i*prim[j]] = 1; // i*prim[j]不是素数
if (i % prim[j] == 0) {
num[i*prim[j]] = num[i] + 1;
d[i*prim[j]] = d[i] / (num[i]+1) * (num[i]+2);
break; // 找到最小素因子即可
}
d[i*prim[j]] = d[i] * d[prim[j]];
num[i*prim[j]] = 1;
}
}
}
int main() {
ll n, x;
getNum();
scanf("%lld", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &x);
printf("%lld\n", d[x]);
}
return 0;
}
#include <stdio.h>
#include <math.h>
int main() {
long long n, x, i, j;
scanf("%lld", &n);
for (i = 1; i <= n; i++) {
scanf("%lld", &x);
long k = long (sqrt(x));
long long sum = 0; // 3 25
for (j = 1; j*j <= x; j++) {
if (x % j == 0) sum += 2;
}
if (x == k * k) sum--;
printf("%lld\n", sum);
}
return 0;
}
求一个数的质因子个数,用一般的方法超时,这个就过了
#include <stdio.h>
int isprim(int k) {
for (int i = 2; i * i <= k; i++) {
if (k % i == 0) return 0;
}
return 1;
}
int main() {
long long m;
while (~scanf("%lld", &m)) {
long long sum = 0;
for (int i = 2; i * i <= m; i++) {
if (isprim(i)) {
while (m % i == 0) {
m /= i;
sum++;
}
}
}
if (m > 1) sum++;
printf("%lld\n", sum);
}
return 0;
}