牛客小白月赛23 C 完全图 题解(二分+__int128or long long 转double)

题目链接

题目思路

首先,一个完全图本身就是一个联通分量。若我们把他变成两个连通分量,最少要把某点和其他点的所有边都去除掉,

也就是要去掉n-1条边。若我们把他变成三个连通分量,在剩下n-1个结点的连通分量上,最少要把某点和其他点的所有边都去除掉,

也就是要去掉n-2条边,以此类推…我们发现规律后就很简单了,显然m越大,最后的答案也会越大,其具有单调性可以二分。

我们设答案为ans,那么ans肯定要满足(n-1)+(n-2)+…+(n-ans)<=m,左边可以直接求和,那么二分找到最大的ans即可。注意求和时

可能炸long long,因此我们要使用__int128,比赛中此题通过人数不是很多,估计就是被高精度坑了。

时间复杂度O(log(n))
——————————————————————————————————————————————————————

首先压缩下了一下范围暴力了一波,t了。后面发现直接二分就行qwq,但是发现炸了long long 然后就wa了。。。。。

后面发现__int128这个神仙东西

__int128不支持标准输入输出,要自己打板子 __int128的一般作用就是做中间值比较

后面想了想,其实可以long long 转double 然后也a了

这个题目最重要的意义就是如果long long炸了却又没有到高精度的地步可以__int128和double

__int128的代码

#include<cstring>
#include<cstdio>
#include<algorithm>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
using namespace std;
int t;
__int128 n,m;
ll a,b;
bool check(__int128 x){
    return (2*n-1-x)*x/2<=m;
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%lld %lld",&a,&b);
        n=a,m=b;
        if(m>=n*(n-1)/2){
            printf("%lld\n",a);
        }else{
            ll l=0,r=n,ans=-1;
            while(l<=r){
                ll mid=l+(r-l)/2;
                if(check(mid)){
                    ans=max(ans,mid+1);
                    l=mid+1;
                }else{
                    r=mid-1;
                }
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

double的代码

#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
const double eps=1e-6;
int t;
ll n,m,ans;
bool check(ll x){
    double sum=1.0*(2.0*n-1-1.0*x)*1.0*x/2;
    return sum-m<=eps;
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%lld %lld",&n,&m);
        if(m>=1.0*n*(1.0*n-1)/2+eps){
            printf("%lld\n",n);
        }else{
            ll l=0,r=n,ans=-1;
            while(l<=r){
                ll mid=l+(r-l)/2;
                if(check(mid)){
                    ans=max(ans,mid+1);
                    l=mid+1;
                }else{
                    r=mid-1;
                }
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}
发布了68 篇原创文章 · 获赞 2 · 访问量 2246

猜你喜欢

转载自blog.csdn.net/m0_46209312/article/details/105233462