题意
中,任选
个数,求两两
的最大值的最小值。
分别对
求取答案。
分析
一个数
放入集合时,它的所有因子一定都在集合中。否则,我们可以用它的某一个因子来代替它,结果只可能更好。这是个很重要的性质,意味着如果
在集合中,那么它参与的
一定是它本身或是它的最大公因子。
那么考虑答案为
时,它一定是集合中某些数的因子。而且这些数的所有因子都在集合中。因此
是这些数的最大真因子。所以答案为
时,以
为最大真因子的数一定都在集合中。
然后
的出现次数就是
作为最大真因子的次数,
出现次数就是
作为最大真因子的次数,
的出现次数就是
作为最大真因子的出现次数。
代码如下
#include <bits/stdc++.h>
#define N 500005
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
LL z = 1;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
int ksm(int a, int b, int p){
int s = 1;
while(b){
if(b & 1) s = z * s * a % p;
a = z * a * a % p;
b >>= 1;
}
return s;
}
int p[N], x[N], c[N], cnt, maxn = N - 5;
LL t;
int main(){
int i, j, n, m;
for(i = 2; i <= maxn; i++){
if(!x[i]) x[i] = p[++cnt] = i;
for(j = 1; j <= cnt; j++){
t = z * i * p[j];
if(t > maxn) break;
x[t] = p[j];
if(i % p[j] == 0) break;
}
}
n = read();
for(i = 2; i <= n; i++) c[i / x[i]]++;
for(i = 1; i <= n; i++){
for(j = 1; j <= c[i]; j++) printf("%d ", i);
}
return 0;
}