传送门
题意:给n-1个点,标号从2到n,点a和点b之间的边权为lcm(a,b),现在求将n-1个点连接起来的最小生成树的边权和
1
≤
T
≤
100
,
1
≤
n
≤
10000000
1\le T\le 100,1\le n\le 10000000
1≤T≤100,1≤n≤10000000
思路:
这个题只给了一个n,n=2只有一个点,那我们贪心地从n=3开始考虑,3肯定连接到2上,n=4时4现在连接到2上更优,n=5时5连接到2上,6的话连接到2或者3都一样
那我们现在就可以思考一下,lcm(a,b)=ab/gcd(a,b),一个数a如果是质数,它与其他比它小的任何数b的lcm都是a * b,那我们这时候把b最小化选择2就可以,如果a是合数,连接上去,我们选择a的一个因子,这样lcm就是a本身,所以最终答案就是 除2以外的质数和2+合数和
这个题n只有1e7,其实比较好做,用个欧拉筛O(n)判断质数即可
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+5;
#define ll long long
int prim[N];
int vis[N];
int cnt;
ll sum1[N]; //素数和
ll sum2[N]; //合数和
void init(){
vis[0]=1;
vis[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])
{
prim[cnt++]=i;
}
for(int j=0;j<cnt&&prim[j]*i<N;j++){
vis[i*prim[j]]=1;
if(i%prim[j]==0) break;
}
}
}
int main(){
init();
for(int i=3;i<N;i++){
if(!vis[i])
{
sum1[i]=sum1[i-1]+i;
sum2[i]=sum2[i-1];
}
else{
sum1[i]=sum1[i-1];
sum2[i]=sum2[i-1]+i;
}
}
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
ll ans=sum1[n]*2+sum2[n];
printf("%lld\n",ans);
}
return 0;
}
埃氏筛优化下复杂度近似O(n),也可以过这个题,代码稍微好写一点
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+5;
#define ll long long
int prim[N];
int vis[N];
int cnt;
ll sum1[N]; //素数和
ll sum2[N]; //合数和
void init(){
vis[0]=1;
vis[1]=1;
for(int i=2;i<N/i;i++){
if(!vis[i]){
for(int j=i*i;j<N;j+=i){
vis[j]=1;
}
}
}
}
int main(){
init();
for(int i=3;i<N;i++){
if(!vis[i])
{
sum1[i]=sum1[i-1]+i;
sum2[i]=sum2[i-1];
}
else{
sum1[i]=sum1[i-1];
sum2[i]=sum2[i-1]+i;
}
}
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
ll ans=sum1[n]*2+sum2[n];
printf("%lld\n",ans);
}
return 0;
}