华为OD机试真题 新系统 9月16号 【统计特殊数字】

统计特殊数字(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 1n 之中,有哪些数字的质因子仅出现在列表 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} 1n1012;列表 nums \text{nums} nums 长度 m m m 范围: 1 ≤ m ≤ 5 1\le m\le5 1m5

输入描述

输入为一行,包含正整数 n n n,质数列表长度 m m m,以及质数列表 nums \text{nums} nums(以数组形式给出)

输出描述

输出一个整数,表示 1 ∼ n 1\sim n 1n 中质因子仅出现在列表 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. 题目要求1-n中,有多少个数的所有质因子都来自给定质数列表,满足条件的数本质就是p1^a1 p2^ a2⋯pm^am≤n,其中m每个质因子指数的ai >=0
  2. 根据1的分析枚举每个质因子的使用次数,统计所有乘积<=n 的不同组合数量就能得到结果。
  3. 由于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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无限码力

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

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

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

打赏作者

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

抵扣说明:

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

余额充值