#P2783. 第1题-小红的整数
-
1000ms
Tried: 30
Accepted: 3
Difficulty: 4
所属公司 :
阿里
时间 :2025年3月31日-阿里国际(算法岗)
-
算法标签>数学
第1题-小红的整数
题解
本题要求找出第 k 个不是 n 的因子的正整数。给定正整数 n,其因子满足一定的规律。我们可以先求出 n 的所有因子,然后利用因子之间的间隔计算出哪些区间内的数字为非因子。具体来说,对于任意一个正整数 x,如果在区间 [1, x] 中 n 的因子个数为 i,那么区间内非因子个数为 x - i。当 x - i 大于等于 k 时,说明第 k 个非因子出现在区间 [1, x] 内,可以直接通过数学关系求出答案。
本题代码采用如下思路:
-
求 n 的因子
遍历 1 至 √n,若 x 为 n 的因子,则将 x 和 n//x 加入因子列表(注意去重),最后对因子列表进行排序。 -
利用因子间隔确定答案
用变量 i 表示遍历到当前的因子数量,对于每个因子 f,区间 [1, f] 内非因子个数为 f - i。如果 f - i ≥ k,则说明第 k 个非因子在 f 之前,可以通过 i+k-1 得到答案;否则继续遍历所有因子。当所有因子遍历完后,说明答案落在 n 之后,此时直接返回 i+k。 -
时间复杂度
求因子集合的时间复杂度为 O(√n),排序因子列表的时间复杂度较低(因子个数最多在 10^5 左右,实际远小于 n),整体时间复杂度可以接受。
Python 代码
# 读入测试用例个数
T = int(input())
while T > 0:
T -= 1
n, k = map(int, input().split())
# 求 n 的因子列表
fs = []
x = 1
while x * x <= n:
if n % x == 0:
fs.append(x) # x 是因子
if x != n // x:
fs.append(n // x) # 加入 n/x
x += 1
# 将因子排序
fs.sort()
# i 表示已经遍历的因子个数
i = 0
flag = False
for f in fs:
i += 1
# 区间 [1, f] 内非因子个数为 f - i
if f - i >= k:
# 第 k 个非因子就是 i + k - 1
print(i + k - 1)
flag = True
break
# 如果在因子区间内没有找到答案,则答案在 n 后面(n 后面的数字都不是 n 的因子)
if not flag:
print(i + k)
JAVA 代码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读入测试用例个数
int T = sc.nextInt();
while(T-- > 0) {
int n = sc.nextInt();
long k = sc.nextLong();
// 求 n 的因子列表,使用 ArrayList 存储
ArrayList<Integer> factors = new ArrayList<>();
for (int x = 1; x * x <= n; x++) {
if(n % x == 0) {
factors.add(x);
if(x != n / x) {
factors.add(n / x);
}
}
}
// 对因子列表排序
Collections.sort(factors);
int i = 0; // 已遍历的因子个数
boolean found = false;
for (int f : factors) {
i++;
// 区间 [1, f] 内非因子数为 f - i
if (f - i >= k) {
// 第 k 个非因子数为 i + k - 1
System.out.println(i + k - 1);
found = true;
break;
}
}
// 如果在因子区间内没有找到答案,则答案在 n 后面
if (!found) {
System.out.println(i + k);
}
}
sc.close();
}
}
C++ 代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while(T--){
int n;
long long k;
cin >> n >> k;
// 求 n 的因子列表
vector<int> factors;
for (int x = 1; x * x <= n; x++){
if(n % x == 0){
factors.push_back(x);
if(x != n / x){
factors.push_back(n / x);
}
}
}
// 对因子列表排序
sort(factors.begin(), factors.end());
int i = 0; // 计数已遍历的因子个数
bool found = false;
for (int f : factors) {
i++;
// 区间 [1, f] 内非因子数为 f - i
if(f - i >= k) {
// 第 k 个非因子数为 i + k - 1
cout << i + k - 1 << "\n";
found = true;
break;
}
}
// 如果在因子区间内没有找到答案,则答案在 n 后面
if(!found) {
cout << i + k << "\n";
}
}
return 0;
}
题目内容
小红有一个正整数n,她想找出第k个不是n的因子的正整数。
例如,当n=6时:6的因子有:1,2,3,6,不是6的因子数依次为:4,5,7,8,9,10,......。如果k=2,答案就是5(第二个不是6的因子的数)
输入描述
第一行输入一个整数t,表示测试用例数。
接下来t行,每行包含两个整数n和k。
1≤t≤1000
1≤n,k≤10^9
输出描述
对于每个测试用例,输出一个整数,表示第k个不是n的因子的正整数。
样例1
输入
2
6 2
6 10
输出
5
14