题目
http://codeforces.com/contest/1292/problem/D
解题思路
从1结点出发,每次枚举是否有大小大于n/2的子树,递归至终点即可
#include <iostream>
using namespace std;
int p[10101],cnt = 0,n,num[10101],sum[10101],t[5050],m[5050][777];
bool notp[10101];
inline int calc(int x,int y) {
int ret = 0;
x /= y;
while (x) {
ret += x;
x /= y;
}
return ret;
}
void init() {
for (int i = 2;i <= 5000; i++) {
for (int j = 2;j *i <= 5000; j++) {
notp[i*j] = 1;
}
if (!notp[i])
p[++cnt] = i;
}
for (int i = 2;i <= 5000; i++) {
int tmp = i;
for (int j = 1;j <= cnt; j++) {
while (!(tmp%p[j]))
tmp /= p[j],num[i]++;
}
sum[i] = sum[i-1]+num[i];
}
for (int i = 1;i <= 5000; i++) {
for (int j = 1;j <= cnt; j++)
m[i][j] = calc(i,p[j]);
}
}
long long ans = 0;
inline void dfs(int st,int ed,int pos,int ci) {
// cout << st << " " << ed << " " << pos << " " << ci << " " << p[pos] << endl;
int tot = 0,tmp = ci+1,last = ed;
for (int i = ed;i >= st; i--) {
//cout << i << " " << tmp << endl;
if (m[i][pos] >= tmp)
tot += t[i];
else {
// cout << i << " " << tmp << endl;
if (tot+tot > n) {
ans -= tot+tot-n;
dfs(i+1,last,pos,tmp);
return ;
}
pos--;
while (!m[i][pos] && pos) {
pos--;
}
if (!pos)
return ;
last = i;
tot = t[i];
tmp = 1;
}
}
if (tot+tot > n) {
ans -= tot+tot-n;
dfs(st,last,pos,tmp);
}
}
int main() {
init();
int aa;
scanf("%d",&n);
for (int i = 1;i <= n; i++) {
scanf("%d",&aa);
ans += sum[aa];
t[aa]++;
}
dfs(0,5000,cnt,0);
printf("%I64d",ans);
return 0;
}