【题解】ABC 210

E.

题意:求最小生成树。

Solution:

数论+生成树。

我们将尝试快速模拟 Kruskal 算法的过程。

发现在第 i 个状态,假设操作前有 A 个联通块,操作后 B 个块,那么代价等于 (A-B) * c[i]

考虑 wv 联通等价于:w=v+k1a1+k2a2+ ... +k_{n-1}a_{n-1},k_i \in Z 。这里根据裴蜀定理得到 w mod d = v mod d ,其中 d=gcd(a1,a2, ... an)

时间复杂度 O(nlogn)

#include<bits/stdc++.h>
#define mp make_pair
#define PII pair<ll,ll>
#define pb push_back
#define vec vector
#define All(x) x.begin(),x.end() 
#define INS(x) inserter(x,x.begin())
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
//Task : Atcoder abc
//Author : cqbzly
ll n,m,cost,tot;
PII A[100005];
ll gcd(ll x,ll y) {
    return (y==0)?x:gcd(y,x%y);
}
int main() {
	cin>>n>>m;
	for(int i=1;i<=m;i++) {
	    cin>>A[i].second>>A[i].first;
	}
	sort(A+1,A+1+m);
	for(int i=1;i<=m;i++) {
	    ll cnt=gcd(A[i].second,n);
	    if(cnt==1) {
	        cost+=(n-1)*A[i].first;
	        cout<<cost;
	        return 0;
	    }
	    else {
	        cost+=(n-cnt)*A[i].first;
	        n=cnt;
	    }
	}
	cout<<"-1";
}

F.

这是一道 2-sat 的题目。

不妨用 vector<int> s[x] 表示有第 x 个质因子的位置 i 的集合。

然而暴力跑 2-sat 时间复杂度 O(n^2) 。(考虑每一个质因子 x ,将 s[x] 元素两两连边) 。

现在我们考虑减少语句数量。首先,我们加入 X_{p,1} , X_{p,2} , ... X_{p,pk} ,然后从 xX_{p,i}=x 连边。这样便于在同一个质数集合内转移。

我们意识到没有必要两两连边,定义 Y_{p,1} 表示前面全为 0 ,同样与 Y_{p,i}=x 建立映射关系。这样的话变的总条数约为 7*\sum{siz_s[x]}

如此时间复杂度 \sum{siz_s[x]}=O(nlogL) 。可以用 tarjan缩点 算法解决。

代码比较冗杂。题解运用了重新编号思想,值得学习。(本人写不出来。。。)

#include<bits/stdc++.h>
#include<atcoder/twosat>
#define ll long long
using namespace std;
//2-sat 算法:可以有向图 tarjan 缩点
//提供一个大常数建边思路。 
int main() {
	ios::sync_with_stdio(false);
	int n; 
	cin>>n;
	atcoder::two_sat ts(n+n*2*7);
	vector<int> v((int)2e6,0);
	int u=n;
	for(int i=0;i<n;i++) {
		int a[2];
		cin>>a[0]>>a[1];
		for(int j=0;j<2;j++) {
			int t=a[j];
			for(int l=2;l<=t;l++) {
				//因为 t<=2e6, 所以不会暴 longlong 
				if(l*l>t) l=t;
				if(t%l) continue;
				while(t%l==0) t/=l;
				if(v[l]>0) {
					//若 x 为 0/1, 则 y 为 0/1  
					ts.add_clause(v[l],false,u,true);
					ts.add_clause(i,j,v[l],false);
				}
				ts.add_clause(i,j,u,true);
				v[l]=u++;
			}
		}
	}
	cout << (ts.satisfiable() ? "Yes" : "No") <<endl;
	return 0;
}
posted @ 2021-07-20 21:56  仰望星空的蚂蚁  阅读(16)  评论(0)    收藏  举报  来源