本解法异常玄乎,但是程序跑得异常的快,我都感到很惊诧: 离天大谱。先给出程序:

#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,那么分布会是:在 1e311e3^1 层有 90 个,在 1e321e3^2 层有 90290^2 个,在 1e3n1e3^n 层有 90n90 ^n 个,于是最大值 1e3log901e51e32.561e3^{log _{90}^{1e5}} ≈1e3^{2.56} ≈47,863,009,但是估计会差一些,取到 1e7 刚好(其实好像最后证明 5e5 对于本题数据就够用了呢)。

于是程序写就,上方已给,感谢您阅读如此一片玄学的题解。

0 comments

No comments so far...

Information

ID
108
Time
1000ms
Memory
256MiB
Difficulty
5
Tags
# Submissions
1
Accepted
1
Uploaded By