专栏文章
题解:CF1731E Graph Cost
CF1731E题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miosrwws
- 此快照首次捕获于
- 2025/12/03 00:33 3 个月前
- 此快照最后确认于
- 2025/12/03 00:33 3 个月前
首先有一个结论,能选大的 就尽量选大的。
证明:我们要使花费代价最小,然而添加的边数是固定的,即,我们要让添加的平均代价最小。那么如果选 条边,平均每条边的代价为 。如果选 条边,平均每条边的代价为 ,通分得 。显然后者代价更小。故得证。
那么我们就从 开始枚举 ,对于每一个枚举到的 ,我们怎么判断有没有 对点能满足 呢?
最大公约数有一个性质:若 ,则 。证明显然,这里不提。
那么我们判断最大公约数就可以转化为:从 到 中有没有 对数互质。
也就是要解决这样一个问题:求 中的互质数组数。
怎么解决?暴力枚举+根号枚举判断?太慢了,是 的。
有互质,可以往欧拉函数上面想。根据欧拉函数的定义,有 。就是说, 为 中,与 互质的数的个数。
这个定义很优美。为什么这么说?可以想到,其前缀和 的值不就是 中,互质数的组数吗?
求 欧拉函数及其前缀和的方法是线性筛,其可以做到 。
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 条评论,欢迎与作者交流。
正在加载评论...