统计特殊数字(Java/Py/C/C++/Js/Go)题解
华为OD机试真题 新系统 华为OD上机考试真题新系统 9月16号 100分题型
华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解
题目内容
已知所有大于
1
1
1 的整数都可以被唯一分解成质数的乘积,我们把这组质数称为该整数的质因子;如:
12
=
2
×
2
×
3
12=2\times2\times3
12=2×2×3,
12
12
12 的质因子为
[
2
,
3
]
[2,3]
[2,3],
7
=
1
×
7
7=1\times7
7=1×7,
7
7
7 的质因子为
[
7
]
[7]
[7]。
现给定一个正整数
n
n
n 和一个质数列表
nums
\text{nums}
nums(数字严格递增),请统计数字
1
∼
n
1\sim n
1∼n 之中,有哪些数字的质因子仅出现在列表
nums
\text{nums}
nums 内,返回符合条件的数字数量。
注意:数字
1
1
1 无质因子,作为符合条件的数字纳入统计。
质数定义:大于
1
1
1 的自然数,除了
1
1
1 和它自身外不能被其他自然数整除的数。
数据范围:整数
n
n
n 范围:
1
≤
n
≤
10
12
1\le n\le10^{12}
1≤n≤1012;列表
nums
\text{nums}
nums 长度
m
m
m 范围:
1
≤
m
≤
5
1\le m\le5
1≤m≤5。
输入描述
输入为一行,包含正整数 n n n,质数列表长度 m m m,以及质数列表 nums \text{nums} nums(以数组形式给出)
输出描述
输出一个整数,表示 1 ∼ n 1\sim n 1∼n 中质因子仅出现在列表 nums \text{nums} nums 内的数字数量。
样例1
输入
10 2
2 3
输出
7
说明
输入参数:上限
n
=
10
n=10
n=10,质数个数
m
=
2
m=2
m=2,允许质因子列表
[
2
,
3
]
[2,3]
[2,3]
统计所有
≤
10
\le 10
≤10 且质因子仅为
2
2
2、
3
3
3 的正整数:
- 1 1 1(无质因子)
- 2 2 2 ( 2 ) (2) (2)
- 3 3 3 ( 3 ) (3) (3)
- 4 4 4 ( 2 2 ) (2^2) (22)
- 6 6 6 ( 2 × 3 ) (2\times3) (2×3)
- 8 8 8 ( 2 3 ) (2^3) (23)
-
9
9
9
(
3
2
)
(3^2)
(32)
共 7 7 7 个,返回结果 7 7 7。
样例2
输入
15 3
2 3 5
输出
11
说明
输入参数:上限
n
=
15
n=15
n=15,质数个数
m
=
3
m=3
m=3,允许质因子列表
[
2
,
3
,
5
]
[2,3,5]
[2,3,5]
统计所有
≤
15
\le 15
≤15 且质因子仅为
2
2
2、
3
3
3、
5
5
5 的正整数:
- 1 1 1(无质因子)
- 2 2 2 ( 2 ) (2) (2)
- 3 3 3 ( 3 ) (3) (3)
- 4 4 4 ( 2 2 ) (2^2) (22)
- 5 5 5 ( 5 ) (5) (5)
- 6 6 6 ( 2 × 3 ) (2\times3) (2×3)
- 8 8 8 ( 2 3 ) (2^3) (23)
- 9 9 9 ( 3 2 ) (3^2) (32)
- 10 10 10 ( 2 × 5 ) (2\times5) (2×5)
- 12 12 12 ( 2 2 × 3 ) (2^2\times3) (22×3)
-
15
15
15
(
3
×
5
)
(3\times5)
(3×5)
共 11 11 11 个,返回结果 11 11 11。
题解
思路:数学原理 + 数学
- 题目要求
1-n中,有多少个数的所有质因子都来自给定质数列表,满足条件的数本质就是p1^a1 p2^ a2⋯pm^am≤n,其中m每个质因子指数的ai >=0 - 根据1的分析枚举每个质因子的使用次数,统计所有乘积<=n 的不同组合数量就能得到结果。
- 由于
m <= 5, 所以可以通过递归算法枚举每个质数的使用次数,找到乘积在n以内合法数字数量即可。
C++
#include <bits/stdc++.h>
#include <vector>
using namespace std;
long long ans = 0;
void dfs(int index , long long cur, vector<long long>& nums, long long n) {
if (index == nums.size()) {
ans++;
return;
}
long long x = cur;
// 枚举当前质数使用次数 0 ,1 ,2...
while (x <= n) {
dfs(index + 1, x, nums, n);
// x * nums[index] > n 不考虑生成大于n的数
if (x > n / nums[index]) {
break;
}
x *= nums[index];
}
}
long long solve(long long n, int m, vector<long long>& nums) {
dfs(0, 1, nums, n);
return ans;
}
int main() {
long long n;
int m;
cin >> n;
cin >> m;
vector<long long> nums(m);
for (int i = 0; i < m; i++) {
cin >> nums[i];
}
cout << solve(n, m, nums);
return 0;
}
Java
import java.util.*;
public class Main {
static long ans = 0;
static void dfs(int index, long cur, long[] nums, long n) {
if (index == nums.length) {
ans++;
return;
}
long x = cur;
// 枚举当前质数使用次数 0 ,1 ,2...
while (x <= n) {
dfs(index + 1, x, nums, n);
// x * nums[index] > n 不考虑生成大于n的数
if (x > n / nums[index]) {
break;
}
x *= nums[index];
}
}
static long solve(long n, int m, long[] nums) {
dfs(0, 1, nums, n);
return ans;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
int m = sc.nextInt();
long[] nums = new long[m];
for (int i = 0; i < m; i++) {
nums[i] = sc.nextLong();
}
System.out.println(solve(n, m, nums));
}
}
Python
import sys
ans = 0
def dfs(index, cur, nums, n):
global ans
if index == len(nums):
ans += 1
return
x = cur
# 枚举当前质数使用次数 0 ,1 ,2...
while x <= n:
dfs(index + 1, x, nums, n)
# x * nums[index] > n 不考虑生成大于n的数
if x > n // nums[index]:
break
x *= nums[index]
def solve(n, m, nums):
dfs(0, 1, nums, int(n))
return ans
data = list(map(int, sys.stdin.read().split()))
n = data[0]
m = data[1]
nums = data[2:2 + m]
print(solve(n, m, nums))
JavaScript
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on('line', line => {
input.push(...line.trim().split(/\s+/));
});
rl.on('close', () => {
let pos = 0;
const n = BigInt(input[pos++]);
const m = Number(input[pos++]);
const nums = [];
for (let i = 0; i < m; i++) {
nums.push(BigInt(input[pos++]));
}
let ans = 0n;
function dfs(index, cur) {
if (index === nums.length) {
ans++;
return;
}
let x = cur;
// 枚举当前质数使用次数 0 ,1 ,2...
while (x <= n) {
dfs(index + 1, x);
// x * nums[index] > n 不考虑生成大于n的数
if (x > n / nums[index]) {
break;
}
x *= nums[index];
}
}
dfs(0, 1n);
console.log(ans.toString());
});
Go
package main
import (
"bufio"
"fmt"
"os"
)
var ans int64 = 0
func dfs(index int, cur int64, nums []int64, n int64) {
if index == len(nums) {
ans++
return
}
x := cur
// 枚举当前质数使用次数 0 ,1 ,2...
for x <= int64(n) {
dfs(index+1, x, nums, n)
// x * nums[index] > n 不考虑生成大于n的数
if x > int64(n)/nums[index] {
break
}
x *= nums[index]
}
}
func solve(n int64, m int, nums []int64) int64 {
dfs(0, 1, nums, n)
return ans
}
func main() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var n int64
var m int
fmt.Fscan(in, &n)
fmt.Fscan(in, &m)
nums := make([]int64, m)
for i := 0; i < m; i++ {
fmt.Fscan(in, &nums[i])
}
fmt.Fprintln(out, solve(n, m, nums))
}
C语言
#include <stdio.h>
long long ans = 0;
void dfs(int index, long long cur, long long nums[], int m, long long n) {
if (index == m) {
ans++;
return;
}
long long x = cur;
// 枚举当前质数使用次数 0 ,1 ,2...
while (x <= n) {
dfs(index + 1, x, nums, m, n);
// x * nums[index] > n 不考虑生成大于n的数
if (x > n / nums[index]) {
break;
}
x *= nums[index];
}
}
long long solve(long long n, int m, long long nums[]) {
dfs(0, 1, nums, m, n);
return ans;
}
int main() {
long long n;
int m;
scanf("%lld", &n);
scanf("%d", &m);
long long nums[m];
for (int i = 0; i < m; i++) {
scanf("%lld", &nums[i]);
}
printf("%lld\n", solve(n, m, nums));
return 0;
}

28万+

被折叠的 条评论
为什么被折叠?



