最小公倍数生成树

题意:

给出n,m,表示又m - n + 1个点的编号从n开始到m结束,两个点之间的权值为编号的最小公倍数,然后求最小生成树。

题解:

因为两个数最小公倍数在最小的情况下,是等于这两个数中较大的那一个数。所以可以贪心地对于一个节点a,连上它的倍数。

有一些情况:

①n = 4 m = 10的时候,因为最后会剩下一个9没有数和它相连,最好的情况下是与6连,从小到大枚举9的因数然后在乘以一个更小的因数使得在n~m的范围。

②n = 2 m = 10的时候,2连向了它所有的倍数,3要连向与2相连的6,最后会剩下以2,5,7为根的子树,现在需要合并子树因为都是素数不是第一种情况的合数,那么就直接合并好了。

代码:

#include <bits/stdc++.h>
using namespace std;

#define LL long long
const int N = 1e6 + 7;
int n, m, prime[N], cnt;
bool isprime[N], vis[N];
LL ans;
void ListofPrime ()
{
	for (int i = 2; i <= 1000000; ++i) isprime[i] = true;
	for (int i = 2; i <= 1000000; ++i)
	{
		if (!isprime[i]) continue;
		prime[++cnt] = i;
		for (int j = 2 * i; j <= 1000000; j += i) isprime[j] = false;
	}
}

int main ()
{
	scanf ("%d%d", &n, &m);
	if (n == m) {
		puts("0");
		return 0;
	}
	if (n == 1) {
		printf ("%lld\n", (LL)(1 + m) * m / 2 - 1);
		return 0;
	}
	ListofPrime();
	for (int i = n; i <= m; ++i)
	{
		if (vis[i]) continue;
		int flag = 0;
		for (int j = 2 * i; j <= m; j += i)
		{
			if (!vis[i] || !vis[j])
			{
				if (vis[j]) flag = 1;
				vis[i] = vis[j] = true;
				ans = ans + j;
			}
		}
		if (vis[i] && i != n && !flag) ans = ans + i * n;
	}
	for (int i = n; i <= m; ++i)
	{
		if (vis[i]) continue;
		if (isprime[i]) ans = ans + i * n;
		else
		{
			for (int j = 2; j <= cnt; ++j)
			{
				if (i % prime[j] != 0) continue;
				for (int k = 1; k < j; ++k)
				{
					int xi = i / prime[j] * prime[k];
					if (xi >= n && xi <= m)
					{
						ans = ans + i * prime[k];
						break;
					}
				}
				break;
			}
		}
	}
	cout << ans << endl;
	return 0;
}

  

总结:

写代码之前需要先考虑好所有的情况,不然就会陷入debug的无限死循环QAQ

时间: 2024-08-08 22:09:53

最小公倍数生成树的相关文章

生成树计数

生成树计数就是统计一张图中一共有多少种构造生成树的方案. 大概要用到组合数学等等的数学知识. 以下内容均来自NOI2007国家集训队论文 周冬 <生成树的计数及其应用>: ------------------------- Matrix-Tree定理(Kirchhoff矩阵-树定理).Matrix-Tree定理是解决生成树计数问题最有力的武器之一.它首先于1847年被Kirchhoff证明.在介绍定理之前,我们首先明确几个概念: 1.G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时

1713:生成树

[题意] 给定一个n个点m条边的无向图,求图中所有生成树边权最大公约数的最小公倍数. [数据规模] 对于20%的数据,M=N-1: 对于另外20%的数据,M=N: 对于另外30%的数据,所有边权都是2的整数次幂: 对于100%的数据,N≤1000,M≤100000,di≤215-1,ans≤264-1. [题解] 先考虑边权都是2的整数次幂的情况,我们可以将每条边的权值改为次数跑最大生成树,2的树上权值最小的边次幂就是答案. 那么我们可以考虑相同做法,对每个边权分解质因数,将该边关于该质因数的次

HDU 1108: 最小公倍数

最小公倍数 #include<iostream> using namespace std; int gcd(int a, int b) { while (b) { int t = a%b; a = b; b = t; } return a; } int lcm(int a, int b) { return a / gcd(a, b)*b; } int main() { ios::sync_with_stdio(false); int a, b; while (cin >> a &g

辗转相除法 求最大公约数和最小公倍数

# include<stdio.h> int main() { int a,b,c,x,y; printf("请输入两个正整数,用逗号间隔:"); scanf("%d,%d",&a,&b); x=a; y=b; if (a<b) { c=a; a=b; //要保证 a>b b=c; } while (b!=0) { c=a; a=b; b=c%b; } c=x*y/a; printf("最大公约数为%d,最小公倍数为

实验 快速生成树配置

[实验名称] 快速生成树协议 RSTP 的配置. [实验目的] 理解快速生成树协议 RSTP 的工作原理,掌握如何在交换机上配置快速生成树. [背景描述] 某学校为了开展计算机教学和网络办公,建立了一个计算机教室和一个校办公区,这两 处的计算机网络通过两台交换机互连组成内部校园网,为了提高网络的可靠性,网络管理员 用 2 条链路将交换机互连,现要在交换机上做适当配置,使网络避免环路. [需求分析] 两台交换机以双链路互联,需要在启用 RSTP 避免环路的同时,提供链路的冗余备份功 能. [实验拓

STP生成树协议的分析总结

一,STP概述 STP(Spanning Tree Protocol,生成树协议)是有应用于交换机之间的防环的.功能是用来防环的. 基本原理: 通过在交换机之间传递一种特殊的协议报文,网桥协议数据单元(BPDU),来确定网络的拓扑结构.BPDU有两种,一种是配置BPDU(configuration BPDU),一种TC BPDU(拓扑变更BPDU). 前者是用于计算无环的生成树的:后者是用于在二层网络拓扑发生变化时产生用来缩短MAC表项的刷新时间的(由默认的300s--->15s) 分类: ST

luoguP1029 最大公约数和最小公倍数问题 [gcd][数论]

题目描述 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数 条件: 1.P,Q是正整数 2.要求P,Q以x0为最大公约数,以y0为最小公倍数. 试求:满足条件的所有可能的两个正整数的个数. 输入输出格式 输入格式: 二个正整数x0,y0 输出格式: 一个数,表示求出满足条件的P,Q的个数 输入输出样例 输入样例#1: 3 60 输出样例#1: 4 说明 P,Q有4种 3 60 15 12 12 15 60 3 先考虑

生成树的基本调整

1.调整vlan的优先级:switch<config># spanning vlan X priority Y       将vlan X的优先级调整为Y,Y是4096的倍数 2.实施端口快速即portfast: 通常情况下,如果生成树中端口状态发生改变,引起生成树从新计算,那么需要大约30s收敛,这是不能承受的. 所以,我们要在连接主机的端口上实施portfast以保证生成树的稳定,它跳过了端口从LIS到LRN,LRN到FWD的过程,收敛速度很快 具体操作有两种,第一种:在所有需要的接口上单

poj3101--Astronomy(分数的最小公倍数)

题目链接:点击打开链接 题目大意:有n个行星,给出每个行星的旋转的周期.问最少多少时间后n个行星会在一条直线上,初始点在一起,不存在全部的行星都有同一个周期 如果A行星的周期是t1.B行星的周期是t2(t2>t1),要在一条直线上,一定会执行的相差半个周期的倍数,时间(t/t2 - t/t1) % (1/2) = 0.也就是t*(t1-t2)/(t1*t2)%(1/2) = 0,要是时间最小.所以也就是差出一个半周期.也就是t = (t2-t1)/(t2*t1*2)这个t也就是A.B执行到一条直