每日一题:Div1 最小生成数

Div1 最小生成数

  • 目录
    • 线性筛介绍
      • 算法简介
      • 原理分析
    • 题目描述
    • 题目思路及代码
  • 结语

目录

线性筛介绍

算法简介

欧拉筛是一个能够做到O(n)的时间复杂度的质数筛法。是目前最优秀的质数筛法,一个十分基础的工具,从原理上掌握它是非常有必要的。

原理分析

  • 核心代码就在这里:
for(ll i=2;i<=Max;i++)
{
	if(!vis[i])
		prime[++count1]=i;
	for(ll j=1;j<=count1 && i*prime[j]<=Max;j++)
	{
    	vis[i*prime[j]]=true;
		if(i%prime[j]==0)
			break;
	}
}

  • 算法的特点就是每个数只会被自己的最小质因数筛过一次。
  • 因为prime中素数是递增的,所以如果i%prime[j]!=0代表i的最小质因数还没有找到,即i的最小质因数大于prime[j]。也就是说prime[j]就是i * prime[j]的最小质因数,于是i*prime[j]被它的最小质因数筛掉了。
  • 如果当i%prime[j]==0时,代表i的最小质因数是prime[j],那么i * prime[j+k] (k>0)这个合数的最小质因数就不是prime[j+k]而是prime[j]了。所以i*prime[j+k]应该被prime[j]筛掉,而不是后续的prime[j+k]。于是在此时break。
  • 综上所述达到了每个数仅筛一次的效果,时间复杂度O(n)。

题目描述

n - 1 个点,从 2 到 n,点 a 与点 b 的边权为 lcm(a,b),求出 n−1 个点的最小生成树

输入格式
第一行一个数字 T。

接下来T行 1 个整数 n。

输出格式
一个数,表示答案。

题目思路及代码

每日一题:Div1 最小生成数_第1张图片

#include 
using namespace std;
#define mod 998244353
const int maxn = 1e7 + 50;
typedef long long int ll;
ll pri[maxn];
ll vis[maxn];
ll dp[maxn];
ll m;
void prime(){
    for(int i=2;i<=maxn;i++){
        if(!vis[i]){
            //cout<
            vis[i]=i;
            if(i!=2)dp[i]=dp[i-1]+2*i;
            pri[++m]=i;
        }else{
            dp[i]=dp[i-1]+i;
        }
        for(int j=1;j<=m;j++){
            if(pri[j]*i>maxn)break;
            vis[i*pri[j]]=pri[j];
            //dp[i*pri[j]]=dp[i*pri[j]-1]+i*pri[j];
            if(i%pri[j]==0)break;
        }
    }
}
int main(){
    prime();
    ll t;
    scanf("%lld",&t);
    while(t--){
        ll x;
        scanf("%lld",&x);
        printf("%lld\n",dp[x]);
    }
    return 0;
}

结语


“遇事不决,可问春风。春风不语,即随本心。”的意思是:对一件事犹豫不决,就问春风该如何做,春风给不出答案,就凭自己本心做出决断。“遇事不决可问春风,春风不语即随本心”一句出自网络作家“烽火戏诸侯”的《剑来》,其原文是:“遇事不决,可问春风。春风不语,遵循己心”。

每日一题:Div1 最小生成数_第2张图片


你可能感兴趣的:(竞赛,动态规划,算法,图论)