[2017纪中11-2]失格 最小生成树+数论
来源:互联网 发布:mac os 终端命令 编辑:程序博客网 时间:2024/06/02 06:20
题面
正解
考场100pts乱搞做法:
首先先去重。
最小生成树从小到大加进边去是没有问题的,于是考虑枚举边长(余数)k,再枚举数a[i],再枚举倍数j,如果a[i]*j+k存在,则连一条边长为k的边,直到合并成数为止。
复杂度O(maxk*nlogP),不知道为什么跑得飞快,比O(nlogP)的正解跑的还快,貌似maxk *n大概是P级别的,此消彼长的那种。。。再加上常数小吧。。。加上x%y<=x%(k *y)的优化跑的更快了。。。
不加优化代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define ll long longusing namespace std;const int maxn=100010;int n,fa[10000010],size[10000010],mxp=0,cnt,a[maxn];bool vis[10000010];ll ans;struct edge{ int x,y,w;}e[1000010];bool cmp(edge a,edge b){ return a.w<b.w;}int getfa(int v){ if(fa[v]==v) return v; fa[v]=getfa(fa[v]); return fa[v];}bool merge(int x,int y){ if(getfa(x)==getfa(y)) return 0; if(size[fa[x]]<size[fa[y]]) swap(x,y); size[fa[x]]+=size[fa[y]]; fa[fa[y]]=fa[x]; return 1;}int read(){ int x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x;}void work(){ cnt=0;ans=0; for(int k=0;k<=mxp&&cnt<n-1;k++) for(int i=1;i<=n;i++) for(int j=1;a[i]*j+k<=mxp;j++) if(fa[a[i]*j+k]!=0&&merge(a[i],a[i]*j+k)) cnt++,ans+=k; }int main(){ n=read(); for(int i=1;i<=n;i++) { int x=read(); mxp=max(mxp,x); fa[x]=x;size[x]=1; } n=0; for(int i=1;i<=mxp;i++) if(fa[i]!=0) a[++n]=i; work(); printf("%lld",ans); return 0; }
加优化代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define ll long longusing namespace std;const int maxn=100010;int n,fa[10000010],size[10000010],mxp=0,cnt,a[maxn];bool vis[10000010];ll ans;struct edge{ int x,y,w;}e[1000010];bool cmp(edge a,edge b){ return a.w<b.w;}int getfa(int v){ if(fa[v]==v) return v; fa[v]=getfa(fa[v]); return fa[v];}bool merge(int x,int y){ if(getfa(x)==getfa(y)) return 0; if(size[fa[x]]<size[fa[y]]) swap(x,y); size[fa[x]]+=size[fa[y]]; fa[fa[y]]=fa[x]; return 1;}int read(){ int x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x;}void work(){ cnt=0;ans=0; for(int i=1;i<=n&&cnt<n-1;i++) for(int j=2;a[i]*j<=mxp;j++) if(fa[a[i]*j]!=0&&merge(a[i],a[i]*j)) cnt++,vis[a[i]*j]=1; int top=0; for(int i=1;i<=mxp;i++) if(fa[i]!=0&&vis[i]==0) a[++top]=i; for(int k=1;k<=mxp&&cnt<n-1;k++) for(int i=1;i<=top;i++) for(int j=1;a[i]*j+k<=mxp;j++) if(fa[a[i]*j+k]!=0&&merge(a[i],a[i]*j+k)) cnt++,ans+=k;}int main(){ n=read(); for(int i=1;i<=n;i++) { int x=read(); mxp=max(mxp,x); fa[x]=x;size[x]=1; } n=0; for(int i=1;i<=mxp;i++) if(fa[i]!=0) a[++n]=i; work(); printf("%lld",ans); return 0; }
阅读全文
0 0
- [2017纪中11-2]失格 最小生成树+数论
- [2017纪中10-28]图 最小生成树+LCT
- [2017纪中10-30]Graph 最小生成树
- 最小生成树 2
- 最小生成树(2)
- 无线通讯网_纪中3078_最小生成树
- 无线通讯网 纪中3078 最小生成树
- java中最小生成树的实现
- 最小生成树(2)
- [2017纪中11-9]乘积 数论+分组背包
- 最小比例 最小生成树
- [2017纪中10-31]Calculate 数论
- poj 2485 Highways prim最小生成树 基础 球最小生成树中得最大边
- 最小生成树&&次最小生成树
- 最小生成生成树计数
- 2017-4-12 最小生成树
- 最小生成树之prim算法2
- 最小生成树2(Kruskal算法)
- Ubuntu 16.04下安装sogou 拼音输入法的错误问题
- CDOJ 360:Another LCIS(区间更新+区间合并)
- LeetCode 155: Min Stack
- matlab矩阵操作
- 如何从现有版本升级到element UI2.0
- [2017纪中11-2]失格 最小生成树+数论
- ASP.NET 事务处理
- hello
- 判断是否有网,判断网络连接,跳转至设置
- Linux命令(1)-cat & 反向tac
- mabatis学习之前今日内容介绍 1、final 关键字 2、static 关键字 3、匿名对象 4、内部类 5、包的声明与访问 6、访问修饰符 7、代码块 第一节课 ###01(面向对象)fin
- POJ 3009
- 2.1.5 自定义view
- Ajax和PHP