- Panda的烦恼
解法2
- 2025-6-9 13:43:55 @
本解法异常玄乎,但是程序跑得异常的快,我都感到很惊诧: 离天大谱。先给出程序:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n , a[105] , k , l , r;
int cmp , cnt , ans[10000005];
void fnd()
{
for ( int i = 1; i <= n; i++ )
for ( int j = 1; j <= cnt && cnt <= 1e7; j++ )
{
l = a[i] * ans[j];
l <= r ? ans[++cnt] = l : 1;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL) , cout.tie(NULL);
cin >> n >> k;
if ( n >= 90 ) r = 5e5;
else r = 2e9;
for ( int i = 1; i <= n; i++ ) cin >> a[i];
ans[1] = 1;
cnt = 1;
fnd();
sort( ans + 1 , ans + cnt + 1 );
cout << ans[k + 1] << endl;
return 0;
}
我的解法是类似于这么一个框架:
for ( int i = 1; i <= n; i++ )
for ( int j = 1; j <= cnt; j++ )
if ( a[i] * ans[j] <= 2e9 )
ans[++cnt] = a[i] * ans[j];
本质其实是递推,但是很隐晦。对于每一个给出的素数,都会将它乘上数组里原有的所有数,并且结果会同时塞进数组里,如果这个值没有超过我们要的极值也就是 2e9。为什么这么做可以?因为在把一些结果塞进去后,这些结果还会在同级被同一个素数再乘一遍、再乘一遍,直到 2e9。而这些结果同样会被以后的素数乘上多遍,所以我们实际上枚举了所有的情况(我都说了很玄学)。
然后我们开心的交上去这个代码,发现一个有趣的事情: 第一个测试样例内存爆了! 很显然为什么错了:数太多了内存炸了,数太多是因为质数太多。
那么如何解决?最玄学的来了,不难发现一个及其有利的事实:当质数越多的时候,数的分布就越密集,也就是说结果的最大值就会越小,我们需要存下来的数也就越少,于是内存就不会爆炸,那么加一个小小的特判:
if ( n >= 90 ) r = 1e7;
else r = 2e9;
这个理论范围这么推导:首先意识到素数越大分布越稀疏,且数目越小分布越稀疏,在 90 以下本程序还可以处理,于是在 n=90 处分析:最大要求第 1e5 个,那么我们推导一下,假设所有质数都取到最大值 1e3,那么分布会是:在 层有 90 个,在 层有 个,在 层有 个,于是最大值 ≈47,863,009,但是估计会差一些,取到 1e7 刚好(其实好像最后证明 5e5 对于本题数据就够用了呢)。
于是程序写就,上方已给,感谢您阅读如此一片玄学的题解。
0 comments
Information
- ID
- 108
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 5
- Tags
- # Submissions
- 1
- Accepted
- 1
- Uploaded By