牛客练习赛127

小红的最大价值



定义一个数对的 ai,aj,i<ja_i, a_j, i < jai​,aj​,i<j 的价值为:如果 ∣ai−aj∣>k|a_i - a_j| > k∣ai​−aj​∣>k,则价值为 max⁡(ai,aj)\max(a_i, a_j)max(ai​,aj​),否则价值为 min⁡(ai,aj)\min(a_i, a_j)min(ai​,aj​)。

#include<bits/stdc++.h>

using namespace std;

int main(){
    int M1 = 0, m1 = 1e9;
    int n, k;
    cin >> n >> k;
    vector<int> a(n);
    for(int i = 0; i < n; i ++)
        cin >> a[i];
    sort(a.begin(), a.end());
    if(abs(a[n - 1] - a[0]) > k)
        cout << a[n - 1];
    else
        cout << a[n - 2];
    return 0;
}

小红的约数



对于一个正整数 nnn 和一个非负整数 ddd,定义 fd(n)f_d(n)fd​(n) 为 nnn 的所有约数的 ddd 次方之和。如 f3(10)=13+23+53+103f_3(10) = 1^3 + 2^3 + 5^3 + 10^3f3​(10)=13+23+53+103。
由于 nnn 可能很大,所以给出 nnn 的质因数分解式。
n=∏i=1wpiain = \prod_{i = 1}^w p_i^{a_i}n=∏i=1w​piai​​

第一行输入一个正整数 www 和一个非负整数 ddd。
接下来 www 行,每行输入两个正整数 pi,aip_i, a_ipi​,ai​。
保证 pip_ipi​ 为素数且互不相同。
 

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;

// 快速幂算法
long long Pow(long long a, long long b) {
    long long res = 1;
    while (b) {
        if (b & 1)
            res = res * a % mod;
        a = a * a % mod;
        b = b >> 1;
    }
    return res;
}

// 使用几何级数公式计算 p^(0*d) + p^(1*d) + ... + p^(a*d)
long long sumOfPowers(long long p, long long a, long long d) {
    if (d == 0) {
        // d 为 0 时,所有的次方都是 1,总和为 a+1
        return (a + 1) % mod;
    }

    long long p_d = Pow(p, d);
    if (p_d == 1) {
        // 如果 p^d == 1, 那么所有的次方都是 1,总和为 a+1
        return (a + 1) % mod;
    }

    // 几何级数和公式
    long long numerator = (Pow(p_d, a + 1) - 1 + mod) % mod;
    long long denominator = (p_d - 1 + mod) % mod;
    long long denominator_inv = Pow(denominator, mod - 2);
    return numerator * denominator_inv % mod;
}

int main() {
    int w, d;
    cin >> w >> d;
    vector<pair<long long, long long>> factors(w);
    for (int i = 0; i < w; i++) {
        cin >> factors[i].first >> factors[i].second;
    }

    long long res = 1;
    for (auto [p, a] : factors) {
        long long sum_powers = sumOfPowers(p, a, d);
        res = res * sum_powers % mod;
    }

    cout << res << endl;
    return 0;
}

小红的图上划分



小红有一个无向图,有 nnn 个点 mmm 条边。小红有 qqq 个询问,每次给出 L,RL, RL,R,求将图划分为至少 LLL 个连通块,最多 RRR 个连通块的最大划分价值,若不可划分输出 "NO ANSWER"。

图的划分定义为将图划分为一个或多个连通块,对于每个连通块,其点集为其边集中每一条边的两端点的集合,且点集内任意两点均可通过边集里的边互相到达。

划分价值定义为所有连通块边集中的最小边权。

#include<bits/stdc++.h>
using namespace std;

//#define ONLINE
#ifndef ONLINE
#define debug(...) fprintf(stderr,##__VA_ARGS__)
#else
#define debug(...) ;
#endif

using LL=long long;
using PII=pair<int,int>;

#define all(x) (x).begin(),(x).end()
#define allr(x) (x).rbegin(),(x).rend()

template<typename T>
inline T READ(){
	T x=0; bool f=0; char c=getchar();
	while(!isdigit(c)) f|=(c=='-'),c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return f?-x:x;
}
inline int read(){return READ<int>();}
inline LL readLL(){return READ<LL>();}
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());

#define N 200010
int fa[N];
int g(int u){
	return u==fa[u]?u:fa[u]=g(fa[u]);
}

void solve(){
	int n=read(),m=read(),T=read();
	vector<array<int,3>>e(m);
	for(int i=0;i<m;i++){
		e[i][0]=read(),e[i][1]=read(),e[i][2]=read();
	}
	sort(all(e),[&](const auto& A,const auto& B)->bool{
		return A[2]>B[2];
	});
	iota(fa+1,fa+n+1,1);
	vector<int>a(n+1,INT_MAX);
	int rest=n;
	for(auto [u,v,w]:e){
		int U=g(u),V=g(v);
		if(U==V) continue;
		a[--rest]=w;
		fa[U]=V;
	}
	for(int l,r;T--;){
		l=read(),r=read();
		if(a[r]==INT_MAX) printf("NO ANSWER\n");
		else printf("%d\n",a[r]);
	}
}

int main(){
	solve();
	return 0;
}

/* stuff you should look for
* int overflow, array bounds
* special cases (n=1?)
* do smth instead of nothing and stay organized
* WRITE STUFF DOWN
* DON'T GET STUCK ON ONE APPROACH
*/

 小红的白点距离



小红有一棵树,初始所有点都是白色。小红最多可以染黑 kkk 个点,定义染色后树的权值为白色点对距离的最大值,求最小的权值。 

/*
首先N^2
预处理所有点对距离
然后二分答案
问题变成N^2判断
给定m条边
是否可以选出最多k个点
使得每条边都有至少一个端点被覆盖
最小点覆盖问题?
像个傻子
显然倒过来
本质上就是让你在原图上选出若干个白点,使得两两最大距离最小
这TM显然是一个连通块
所以再次二分答案
钦定连通块最长不超过mid
是否可能选出一个大小>=n-k的连通块
设f[u,k]:子树u选出k个点,在满足直径不超过mid的情况下
其最短的链长是多少
改一下
我们枚举这个连通块的某个边缘节点
也就是根
不了
我们就用:
f[u,k]:最长深度为k时,最多选出点数
f'[u,max(p,q)]=f[u,p]+f[v][q],p+q<=mid
*/
#include<bits/stdc++.h>
using namespace std;
#define N 1050
int read(){
	int x=0,w=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')w=(ch=='-'?-w:w),ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*w;
}
void print(int x){
	if(x<0)putchar('-'),print(-x);
	else if(x<10)putchar('0'+x);
	else print(x/10),putchar(x%10+'0');
}
vector<int>e[N];
int mid,g[N],f[N][N],siz[N],mx=0;
void dfs(int u,int fa){
    f[u][0]=1;siz[u]=1;
    for(auto v:e[u]){
        if(v==fa)continue;
        dfs(v,u);
        for(int i=0;i<=siz[u];i++)for(int j=0;j<=siz[v];j++){
            if(!f[u][i])continue;if(!f[v][j])continue;
            if(i+j+1<=mid)g[max(i,j+1)]=max(g[max(i,j+1)],f[u][i]+f[v][j]);
        }
        siz[u]+=siz[v];
        for(int i=0;i<=siz[u];++i)f[u][i]=max(f[u][i],g[i]),g[i]=0;
    }
//     cout<<u<<": ";
//     for(int i=0;i<=siz[u];i++)cout<<f[u][i]<<" ";cout<<"\n";
    for(int i=0;i<=siz[u];i++)mx=max(mx,f[u][i]);
}
int main(){
    int n=read(),k=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        e[u].push_back(v);e[v].push_back(u);
    }
    int l=1,r=n;
    while(l<r){
        mid=l+r>>1;mx=0;
//         cout<<mid<<"!\n";
        memset(f,0,sizeof f);
        dfs(1,0);
        if(mx>=n-k)r=mid;
        else l=mid+1;
    }
    cout<<l<<"\n";
}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值