zoukankan      html  css  js  c++  java
  • 【洛谷P7854】GCD Tree

    题目

    题目链接:https://www.luogu.com.cn/problem/P7854
    给你 (n) 个点,编号分别为 (1,2,ldots,n),点权分别为 (a_1,a_2,ldots,a_n)
    请你用这 (n) 个点构造一棵树,使得 (forall 1 le i < j le n)(gcd(a_i, a_j) = a_{operatorname{lca}(i, j)})
    若无解,报告之,否则输出树的形态。

    思路

    首先可以把序列排序去重,相同点权的点全部连向其中一个就行了。下面所有点的编号都是点权。
    对于一个点 (x),显然其子树内所有点都是 (x) 的倍数。同时所有 (x) 倍数的点都必须在 (x) 的子树内。
    那么对于 (x) 的倍数 (y),如果 (y) 没有父节点,则把 (y) 的父节点设为 (z);如果 (y) 已经有父节点 (z) 了,且 (z) 不是 (x) 的倍数,那么显然无解;如果 (y) 的父节点 (z)(x) 的倍数,那么只需要考虑 (z)(x) 之间的连边,可以不用改 (y) 的父亲。
    从大到小枚举 (x) 跑一遍就好了。
    但是这样搞出来的数只能保证 (a_{ ext{lca}(i,j)}|gcd(a_i,a_j))。并不一定合法。也就是说,我们只需要把不合法情况判掉就行了。
    下面的思路是我抄 QuantAsk 神仙的 /bx
    如果对于所有 ((i,j)) 都有存在权值为 (gcd(a_i,a_j)) 的点,那么我们的构造是一定合法的。且这个东西是充要的。
    所以可以容斥一下求出每一个数作为 (gcd) 出现的次数,如果任意一个数 (x) 作为 (gcd) 出现过,但是没有权值为 (x) 的点,就无解了。
    时间复杂度 (O((n+V)log V))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=1000010;
    int n,m,a[N],b[N],fa[N],pos[N];
    ll cnt[N];
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		b[i]=a[i]; cnt[a[i]]++;
    		if (!pos[a[i]]) pos[a[i]]=i;
    	}
    	for (int i=1;i<=1e6;i++)
    		for (int j=i*2;j<=1e6;j+=i)
    			cnt[i]+=cnt[j];
    	for (int i=1e6;i>=1;i--)
    	{
    		cnt[i]*=cnt[i];
    		for (int j=i*2;j<=1e6;j+=i)
    			cnt[i]-=cnt[j];
    		if (cnt[i] && !pos[i]) return printf("-1"),0;
    	}
    	sort(a+1,a+1+n);
    	m=unique(a+1,a+1+n)-a-1;
    	for (int i=m;i>=1;i--)
    		for (int j=a[i]*2;j<=1e6;j+=a[i])
    			if (pos[j])
    			{
    				if (!fa[j]) fa[j]=a[i];
    				if (fa[j]%a[i]) return printf("-1"),0;
    			}
    	for (int i=2;i<=m;i++)
    		if (!fa[a[i]]) return printf("-1"),0;
    	for (int i=1;i<=n;i++)
    		if (pos[b[i]]!=i) cout<<pos[b[i]]<<" ";
    			else cout<<pos[fa[b[i]]]<<" ";
    	return 0;
    }
    
  • 相关阅读:
    FJNU 1151 Fat Brother And Geometry(胖哥与几何)
    FJNU 1157 Fat Brother’s ruozhi magic(胖哥的弱智术)
    FJNU 1159 Fat Brother’s new way(胖哥的新姿势)
    HDU 3549 Flow Problem(最大流)
    HDU 1005 Number Sequence(数列)
    Tickets(基础DP)
    免费馅饼(基础DP)
    Super Jumping! Jumping! Jumping!(基础DP)
    Ignatius and the Princess IV(基础DP)
    Keywords Search(AC自动机)
  • 原文地址:https://www.cnblogs.com/stoorz/p/15229013.html
Copyright © 2011-2022 走看看