[NOIP模拟赛]吃糖果
来源:互联网 发布:多功能测量仪软件 编辑:程序博客网 时间:2024/06/05 00:56
题目描述
小D有一包糖果和N张卡片。每张卡片上都有一个正整数Pi。小D想这样吃糖果,他把两张卡片用线串起来,如果两张卡片上的数字分别为Pa和Pb,他就吃掉min(Pa%Pb,Pb%Pa)的糖果。
他想最终把所有的卡片都串起来——即提起一张卡片,就可以将其他卡片都提起。请问他最少需要吃掉多少糖果。
输入格式
第一行包含一个正整数N(1≤N≤10^5)
接下来N行,每行一个正整数Pi(1≤Pi≤10^7)
输出格式
有且只有一行,输出答案。
输入样例
3
4
915
输出样例
4
题解:最小生成树
如果两张卡片上的数相等,那么他们之间边权为0,可以将他们看做一个顶点。于是我们只需要考虑卡片上的互不相等的情况。
设卡片的最大值为maxz,注意到maxz不超过10^7,将卡片按值由小到大排序,对于某张卡片i,设它的值为pi。以pi为周期,将[pi,maxz]分为若干个区间,最后一个区间可能不足pi。在每个区间找到模pi的值最小的卡片,将该卡片和卡片i连边。特别的,第一个区间即[pi,2*pi-1],要注意不能找第i张卡片本身。
我们只需要在刚才连的边中求一个最小生成树即可。
此时的边数最多为maxz*log(maxz)。
然后注意边权在10^7以内,所以,我们可以使用计数排序。这样,时间复杂度为O(N+maxz*log(maxz))
#include<cstdio>#include<vector>using namespace std;const int N=1e5+10;const int M=1e7;int n, p[N], rot[N], h[N], cnt[M+5];int Root( int x ) {if( !rot[x] ) return x;return rot[x]=Root( rot[x] );}int realv[M+5];//realv[i]:记录原值为i的位置被修改后的值int pos[M+5];//pos[i]:记录i这个值最先出现的标号struct node{ int s, e; node() {} node( int a, int b ) { s=a; e=b; } };vector<node> edge[M+5];long long sum;int main() {scanf( "%d", &n );for( int i=1; i<=n; i++ ) {scanf( "%d", &p[i] );realv[ p[i] ]=p[i];if( !pos[ p[i] ] ) pos[ p[i] ]=i;}for( int i=M; i>=0; i-- )if( !realv[i] ) realv[i]=realv[i+1];for( int i=1; i<=n; i++ ) {if( cnt[ p[i] ]++ ) continue;if( realv[ p[i]+1 ] )//特殊处理第一个区间[ p[i], 2*p[i] )if( realv[ p[i]*2 ]!=realv[p[i]+1] || p[i]*2>M )edge[ realv[p[i]+1]-p[i] ].push_back( node( i, pos[ realv[p[i]+1] ] ) );for( int j=p[i]*2; j<=M && realv[j]; j+=p[i] )if( realv[ j+p[i] ]!=realv[j] || j+p[i]>M )edge[ realv[j]-j ].push_back( node( i, pos[ realv[j] ] ) );}for( int i=0; i<=M; i++ )for( int j=0; j<(int)edge[i].size(); j++ ) {int s=Root( edge[i][j].s ), e=Root( edge[i][j].e );if( s!=e ) {if( h[s]<h[e] ) rot[s]=e;else rot[e]=s;if( h[s]==h[e] ) h[s]++;sum+=i;}}printf( "%I64d\n", sum );return 0;}
阅读全文
0 0
- [NOIP模拟赛]吃糖果
- #NOIP模拟赛#吃糖果candy(缩小选边范围--mod区间)
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- 吃糖果
- JavaScript 小结
- 电影《内布拉斯加/百万奖金梦》观后感悟
- Retrofit用法详解
- C#下使用protobuf(Google Protocol Buffers)
- 用ceph-deploy安装ceph并部署集群
- [NOIP模拟赛]吃糖果
- HashMap与ConcurrentHashMap的区别
- FluctuationTime.jar java日期时间操作:增减时间、取时间间隔、取年、取月、取日、取时、取分、取秒、日期时间比较大小精确到年月日时分秒 取当月有多少天 日期时间自由操作精确到秒
- 持有对象
- 网易笔试编程题1
- 11.UML图_类之间的关系
- C++闭包示例
- 学习笔记之面向对象编程5(object类,tostring方法)
- 美团点评2017年秋招笔试题