题意
给一个$n(\le 10^7)$,求由$n-1$个点$2$, $3$, $\cdots$, $n$构成的最小生成树的边权和,其中点$a$, $b$之间的连边的权值为$\text{lcm} (a,b)$。
思路
考虑加点连边,若加入$u$连接到$v$,则权值和增加$\text{lcm}(a,b)\ge u$,下界当且仅当$v|u$时取得。则当所有数都与小于其自身的某个因数(若存在。不妨设为最小质因子)连接时,权值和增量最小,为加入的数本身。此时除$2$到$n$之间所有质数外,其他数均与其最小质因子连接,则问题转化为将$2$到$n$之间所有质数为树根的子树连接成一棵树。考虑边权为$\text{lcm}$,则将树根间相连最优。又当$p,q\in prime$时,$\text{lcm}(p,q)=pq$,则将$3$到$n$的所有质数与$2$相连最优。
由此可得答案为$\displaystyle \sum_{i=3}^{n}i+\sum_{i=3}^{n}[i\in prime]i$。
时间复杂度$\mathcal{O}(n)$。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| #include<bits/stdc++.h> using namespace std; #define debug printf("%d %s\n",__LINE__,__FUNCTION__);fflush(stdout) using ll=long long;using i64=long long;using db=double; using u32=unsigned int;using u64=unsigned long long;using db=double; using pii=pair<int,int>;using vi=vector<int>; using qi=queue<int>;using pqi=priority_queue<int>;using si=set<int>; #define pb push_back #define mk make_pair #define ins insert #define era erase #define fi first #define se second #define lowbit(x) x&-x #define ALL(a) a.begin(),a.end() const int INF=0x3f3f3f3f; const ll INFLL=0x3f3f3f3f3f3f3f3f; const double PI=acos(-1.0); template<class T>inline bool chkmin(T&a,T b){return b<a?a=b,true:false;} template<class T>inline bool chkmax(T&a,T b){return a<b?a=b,true:false;} int _w,_t;FILE* _f; #define MULTI_CASES
const int N=1e7+7; int n,notpr[N]; ll sum[N];
void init(){ notpr[0]=notpr[1]=1; sum[1]=-4; for(int i=2;i<N;i++){ sum[i]=sum[i-1]+i; if(!notpr[i]){ sum[i]+=i; for(int j=i<<1;j<N;j+=i){ notpr[j]=1; } } } }
void solve(){ scanf("%d",&n); printf("%lld\n",sum[n]); }
int main(){ init(); #ifdef MULTI_CASES _w=scanf("%d",&_t);while(_t--) #endif solve(); return 0; }
|