专栏文章

题解:CF1731E Graph Cost

CF1731E题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miosrwws
此快照首次捕获于
2025/12/03 00:33
3 个月前
此快照最后确认于
2025/12/03 00:33
3 个月前
查看原文
首先有一个结论,能选大的 kk 就尽量选大的。
证明:我们要使花费代价最小,然而添加的边数是固定的,即,我们要让添加的平均代价最小。那么如果选 kk 条边,平均每条边的代价为 k+1k\dfrac{k+1}{k}。如果选 k+1k+1 条边,平均每条边的代价为 k+2k+1\dfrac{k+2}{k+1},通分得 k2+2k+1k2+k>k2+2kk2+k\dfrac{k^2+2k+1}{k^2+k}>\dfrac{k^2+2k}{k^2+k}。显然后者代价更小。故得证。
那么我们就从 nn 开始枚举 kk,对于每一个枚举到的 kk,我们怎么判断有没有 k+1k+1 对点能满足 gcd(u,v)=k+1\gcd(u,v)=k+1 呢?
最大公约数有一个性质:若 gcd(u,v)=g\gcd(u,v)=g,则 ugvg\frac{u}{g}\bot\frac{v}{g}。证明显然,这里不提。
那么我们判断最大公约数就可以转化为:从 11nk+1\frac{n}{k+1} 中有没有 k+1k+1 对数互质。
也就是要解决这样一个问题:求 [1,p][1,p] 中的互质数组数。
怎么解决?暴力枚举+根号枚举判断?太慢了,是 O(n2n)O(n^2\sqrt n) 的。
有互质,可以往欧拉函数上面想。根据欧拉函数的定义,有 ϕ(n)=i=1nni\phi(n)=\sum\limits_{i=1}^nn\bot i。就是说, ϕ(n)\phi(n)[1,n][1,n] 中,与 nn 互质的数的个数。
这个定义很优美。为什么这么说?可以想到,其前缀和 sum=i=1nϕ(i)sum=\sum\limits_{i=1}^n\phi(i) 的值不就是 [1,n][1,n] 中,互质数的组数吗?
[1,n][1,n] 欧拉函数及其前缀和的方法是线性筛,其可以做到 O(n)O(n)
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e6+10;
int phi[N],sum[N],Prime[N],cnt;
bool vis[N];
void Getphi(){
	phi[1] = 1;
	for(int i = 2;i<N;i++){
		if(!vis[i]){
			vis[i] = i;
			Prime[++cnt] = i;
			phi[i] = i - 1;
		}
		for(int j = 1;j<=cnt;j++){
			if(i*Prime[j] > N) break;
			vis[i*Prime[j]] = Prime[j];
			if(i%Prime[j] == 0){
				phi[i*Prime[j]] = phi[i]*Prime[j];
				break;
			}
			phi[i*Prime[j]] = phi[i]*phi[Prime[j]];
		}
		sum[i] = sum[i-1] + phi[i];
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int T; cin>>T;
	Getphi();
	while(T--){
		int n,m,ans = 0;
		cin>>n>>m;
		for(int k = n;k>=1;k--){
			int maxn = min(sum[n/(k+1)],m)/k;
			ans += maxn * (k+1);
			m -= maxn * k;
		}
		cout<<(m > 0 ? -1 : ans)<<'\n';
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...