魅力程序猿

  • 首页
  • Java
  • Android
  • APP
    • 扑克计分器
    • Video Wallpaper
  • 联系我
  • 关于我
  • 资助
道子
向阳而生
  1. 首页
  2. AI技术
  3. 正文

5.10 周赛vp 2026 ICPC Gran Premio de Mexico 1ra Fecha E题

2026年5月12日 8点热度 0人点赞 0条评论

📰 来源: 博客园


原题链接:https://codeforces.com/gym/106495/problem/E

将 \(1 \sim N\)内的数,按其质因数分解序列的字典序进行排序,并回答\(Q\)次查询,每次求排在第\(K\) 位的数字是谁。

赛时队长大大灵机一动,突然受2025年省赛B题[https://qoj.ac/contest/2021/problem/10724]
暴力解法\(O(N\ logN)\):跑两次for循环,用每个数的最小质因数标记该数
的思路启发,神来之手一发ac

/ 把队长ac代码小小优化过后,附上:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAX = 1e6+5;
#define all(a) (a).begin()+1, (a).end()

void work(){
	int n, q, k;
	cin >> n >> q;
	vector<int> a(n+1), p(n+1);
	for(int i=2; i<=n; i++){ // 跑两次for循环,用每个数的最小质因数标记该数
		for(int j=i; j<=n; j+=i){
			if(!p[j]) p[j] = i;
		}
	}
		

	for(int i=1; i<=n; i++) a[i] = i;
	
	sort(all(a), [&](int x, int y){ // 迭代写法
		while(p[x] == p[y]){ // 不断剔除相同的最小质因数,直到遇到不同的
			if(p[x] == 0) return false;
			x /= p[x];
			y /= p[y];
		}
		return p[x] < p[y];
	});

	while(q--){
		cin >> k;
		cout << a[k] << '\n';
	}
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int T = 1;
//	cin >> T;
	while(T--) work();
}

/另附赛后补题的 常规解法:

核心思路:欧拉筛 + DFS

题目要求的质因数序列字典序,恰好完美契合深度优先搜索(DFS)的前序遍历顺序。

预处理素数(欧拉筛):

使用欧拉筛预先求出 \(1 \sim N\) 范围内的所有素数,并从小到大保存在 prime 数组中。

构造搜索树(DFS):

我们可以把数字看作是从 \(1\) 开始,不断乘以素数衍生出来的。

根节点:数字 \(1\)(对应空序列 \([]\)),首先将其加入答案数组。

分支:当前数字去乘以一个素数 \(p\)。为了保证质因数序列是非降序的(避免 \(2 \times 3\) 和 $3 \times 2$ 重复,且符合题目定义),每次 DFS 扩展时,只能乘以大于等于前一个质因数的素数(即代码中的 for (int i = idx; ...))。
剪枝:如果 当前数字 * 质数 > N,说明越界了,直接 break 结束当前分支。

时间复杂度:预处理 \(O(N)\)(欧拉筛 \(O(N)\) + DFS遍历 \(1 \sim N\)每个数恰好一次\(O(N)\));查询 \(O(1)\)。总时间 \(O(N + Q)\)。
空间复杂度:\(O(N)\),用于存储素数和最终的答案数组。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) (a).begin(), (a).end()

const int MAX = 1e6+5;
vector<int> prime, minp, maxp;

void euler(int n = MAX) {
    minp.resize(n + 1);
    maxp.resize(n + 1);
    for (int i = 2; i <= n; i++) {
        if (!minp[i]) {
            minp[i] = maxp[i] = i;
            prime.push_back(i);
        }
        for (auto j : prime) {
            if (j > minp[i] || j > n / i) break;
            minp[i * j] = j;
            maxp[i * j] = maxp[i];
        }
    }
}

void solve(){
	int n, q;
	cin >> n >> q;
	
	// for(int i=0; i<n; ++i){
	// 	cout << prime[i] << " ";
	// }
	vector<ll> ans;
	ans.push_back(1);

	auto dfs = [&](auto &&self, ll sum, int idx) ->void {
		for(int i=idx; i<prime.size(); ++i){
			ll v = sum * prime[i];
			if(v > n) break;
			ans.push_back(v);
			self(self, v, i);
		}
	};

	dfs(dfs, 1, 0);

	for(int i=0; i<q; ++i){
		int x;
		cin >> x;
		cout << ans[x-1] << '\n';
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	euler();
	int T = 1;
//	cin >> T;
	while(T--) solve();
}
/*
1
2
2*2
2*2*2
2*3
2*5
3
3*3
5
7
*/

🔗 原文链接: 点击阅读原文

标签: AI 人工智能 技术博客
最后更新:2026年5月12日

daozi

这个人很懒,什么都没留下

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复
搜索
联系方式

QQ群:179730949
QQ群:114559024
欢迎您加入Android大家庭
本人QQ:136049925

赐我一丝安慰
给我一点鼓励

COPYRIGHT © 2023 魅力程序猿. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

豫ICP备15000477号