zoukankan      html  css  js  c++  java
  • NOIP2020模拟赛(拾)解题报告

    PS:大家注意一下 蛤->拾 出题人打错了

    A. 「NOIP模拟赛 蛤」ZigZagK的生成树

    「NOIP模拟赛 蛤」ZigZagK的生成树

    solve

    这道题我们要抓住一个性质,如果(a)可以被(b)整除,则(gcd(a,b)=b),所以我们建边是要和他的最大约数建边,质数就和1建边,我们可以从大到小枚举约数,去连他的倍数,但我们发现,一个数可能被链接多次,产生环,用并查就可以判断是否出现环,有点像Kruskal一样,由于约数是从大到小来枚举的,所以就不用排序了,这里要注意一个结论(1+frac{1}{2}+frac{1}{3}+frac{1}{4}+...+ frac{1}{n}=ln(n)+R),其中(R)是欧拉常数,值为(0.57721566490)左右。所以时空复杂度约为(O(nln(n)))

    code

    #include<bits/stdc++.h>
    #define LL long long 
    using namespace std;
    inline void read(LL &x)
    {
    	LL f=1;x=0;char ch=getchar();
    	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    	while (isdigit(ch)){x=(x<<3)+(x<<1)+(ch&15);ch=getchar();}
    	x*=f;
    }
    LL n,cnt=0,fa[1000005],ans=0;
    inline LL getfa(LL x){if (x==fa[x]) return x;return fa[x]=getfa(fa[x]);}
    int main()
    {
    	read(n);
    	for (LL i=1;i<=n;i++) fa[i]=i;
    	for (LL i=n;i>=1;i--)
    	  for (LL j=2;j<=n/i;j++)
    	  {
    		LL fx=getfa(i),fy=getfa(i*j);
    	  	if (fx!=fy) {fa[fx]=fy,ans+=i,cnt++;if (cnt==n-1) break;}
    	  }	
    	cout<<ans<<endl;
    	return 0;
    }
    

    B. 「NOIP模拟赛 蛤」Lynstery的生成树

    B. 「NOIP模拟赛 蛤」Lynstery的生成树

    solve

    话说这道题的描述是真的坑,我读了一个半小时才搞懂题目在干嘛,简化的来说,就是给出一个图,找任意个基环树,使得边权加和最大,我们用一个贪心的想法,从边权最大的地方开始取,用并查集来判断哪些节点是在一棵树里面的,每棵树最多只有一个圈,我们可以开一个(h[])数组来记录是否有环,如果有两个环了就不连接了。

    代码还是很好实现的。

    code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    int N,M,fa[100005],h[100005];
    long long ans;
    struct AS{
    	int x,y,w;
    	bool operator <(const AS B)const {return w>B.w;}
    }a[100005];
    inline int read() {
        int f=1,x=0;
        char ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-') f=-f;ch=getchar();}
        while('0'<=ch&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}
    int main(){
    //	freopen("2.in","r",stdin);
    //	freopen("2.out","w",stdout);
    	N=read();M=read();
    	for(int i=1;i<=M;i++)a[i].x=read(),a[i].y=read(),a[i].w=read(),fa[i]=i;
    	sort(a+1,a+1+M);
    	for(int i=1;i<=M;i++){
    		int fx=get(a[i].x),fy=get(a[i].y);
    		if(fx==fy){
    			if(h[fx]!=0)continue;
    			ans+=(LL)a[i].w;
    			h[fx]=1;
    		}
    		else {
    			if(h[fx]==1&&h[fy]==1)continue;
    			else if(h[fx]==1){
    				fa[fy]=fx;
    				ans+=(LL)a[i].w;
    			}
    			else if(h[fy]==1){
    				fa[fx]=fy;
    				ans+=(LL)a[i].w;
    			}
    			else {
    				fa[fx]=fy;
    				ans+=(LL)a[i].w;
    			}
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    C.「NOIP模拟赛 蛤」Axcosin的生成树

    C. 「NOIP模拟赛 蛤」Axcosin的生成树

    solve

    你别被他的图骗了,其实就是一个线性问题,(想我就被骗了) 用贪心的想法,排序后,最大的和最小的匹配,如果超过S就抵消掉,如果没有超过S就往里面推,那个图就是一个幌子,还是一个数字匹配的问题,哎wtcl。

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=500005;
    int n,m,a[maxn],ans;
    bool vis[maxn];
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while (ch<'0'||ch>'9'){if (ch=='-') f=-f;ch=getchar();}
    	while (ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    	return ret*f;
    }
    int main(){
    	n=read();m=read();
    	for (int i=1;i<=n;i++) a[i]=read();
    	sort(a+1,a+n+1);int R=n;
    	for (int i=1;i<R;i++){
    		if (a[i]+a[R]>=m) R--,ans++;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    我永远是最菜的!!!

    over

  • 相关阅读:
    python学习笔记之——unittest框架
    python学习笔记——python JSON
    python学习笔记之——操作mysql数据库
    python学习笔记之——python安装mysqldb后,pycharm导入还是报错问题
    python学习笔记之——python面向对象
    Python学习笔记之—— File(文件) 对象常用函数
    python学习笔记之——文件I/O
    Linux下免安装版sublime text 3显示图标
    PL/SQL客户端中执行insert语句,插入中文乱码
    RocksDB安装
  • 原文地址:https://www.cnblogs.com/martian148/p/13332953.html
Copyright © 2011-2022 走看看