constint N = 2e5 + 10; int n, m, k, a[N], mark[N], ret[N], cnt; typedeflonglong ll; ll tot; structnode { int id, num; }b[N];
boolcmp(node a, node b){ return a.num > b.num; }
intmain(){ cin >> n >> m >> k; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); b[i].num = a[i], b[i].id = i; } sort(b + 1, b + n + 1, cmp); for (int i = 1; i <= m * k; i++) { mark[b[i].id] = 1; tot += b[i].num; } int sum = 0; for (int i = 1; i <= n; i++) { if (mark[i]) sum++; if (sum == m) ret[++cnt] = i, sum = 0; } printf("%lld\n", tot); for (int i = 1; i < cnt; i++) printf("%d ", ret[i]); puts(""); return0; }
众所周知,1 ~ n 中 p 的倍数的个数为 n / p 下取整。这里我们要找出对于每一个 p,它作为因子的个数,即 f(n, p). f(n, p) = n / p + n / (p ^ 2) + n / (p ^ 3). 注意求 f(n, p) 的时候不能先算 (p ^ k), 而应该用不断除的形式,避免精度误差,这一段下面代码中有具体方法。
typedeflonglong ll; ll n, b, ans; ll ok[1000010], prime[1000010], cnt;
voidIs(){ for (int i = 2; i <= 1000000; i++) { if (!ok[i]) prime[++cnt] = i; elsecontinue; for (int j = 2; i * j <= 1000000; j++) ok[i * j] = 1; } }
ll f(ll x, ll y){ ll tmpN = x, res = 0; while (tmpN) tmpN /= y, res += tmpN; return res; }
intmain(){ scanf("%lld%lld", &n, &b); Is(); ans = 1e18; ll tmp = b; for (int i = 1; i <= cnt; i++) { ll p = prime[i]; if (p > b) break; if (b % p) continue; ll tot = 0; while (tmp % p == 0) tmp /= p, tot++; ll now = f(n, p) / tot; ans = min(ans, now); } if (tmp > 1) ans = min(ans, f(n, tmp)); printf("%lld\n", ans); return0; }