“蔚来杯“2022牛客暑期多校训练营4 补题题解(A、D、H、K、N)


觉得有帮助的点个赞!

比赛地址
参考的大佬题解
怒写一夜题解,第一次一天补一场,继续加油!

A Task Computing

请添加图片描述

请添加图片描述
请添加图片描述

#include<bits/stdc++.h>

using namespace std;

#define db double

const int N = 1e5 + 10;

struct Node{
	db w;
	db p;
	bool operator < (const Node &t) const {
		return w + p * t.w < t.w + t.p * w;
	}
}a[N];

db f[N][30];  //f[i][j]表示前i件物品中拿j件的最大价值 

int n, m;

int main()
{
	cin>>n>>m;
	for(int i = 1; i <= n; i ++ ){
		cin>>a[i].w;
	}
	for(int i = 1; i <= n; i ++ ){
		cin>>a[i].p;
		a[i].p /= 10000; 
	}
	
	sort(a + 1, a + n + 1);
	
	for(int i = 1; i <= n; i ++ ){
		for(int j = 1; j <= min(i, m); j ++ ){
			f[i][j] = max(f[i - 1][j], a[i].w + a[i].p * f[i - 1][j - 1]);
		}
	}
	printf("%.12f", f[n][m]);
	
	return 0;
}

D Jobs (Easy Version)

请添加图片描述

#include<bits/stdc++.h>
#include <random>

using namespace std;

const int N = 410, M = 2e6 + 10, mod = 998244353;

int dp[12][N][N];  //dp[i][j][k]记录第i个公司要求 IQ <= i, EQ <= j,的职位的最低AQ要求
int n, m;
long long qq[M];
long long ans;

int solve(int IQ, int EQ, int AQ){
	int res = 0;
	for(int i = 1; i <= n; i ++ ){
		if(dp[i][IQ][EQ] <= AQ) res ++ ;
	}
	return res;
}

signed main()
{
	cin>>n>>m;
	memset(dp, 0x3f3f3f3f, sizeof dp);
	for(int i = 1; i <= n; i ++ ){
		int cnt;
		cin>>cnt;
		while(cnt -- ){
			int a, b, c;
			cin>>a>>b>>c;
			dp[i][a][b] = min(dp[i][a][b], c);
		}
		//二维偏序操作
		//原本dp[i][k][d]记录的是第i个公司IQ=k,EQ=d的职位的最低阿Q值
		//经过二维偏序dp[i][k][d]就变成记录i个公司IQ <= k,EQ <= d的职位的最低阿Q值
		//我在这卡了半天思维,不懂得话可以带几组数据或者去B站听emo的面向新手讲题 
		for(int k = 1; k <= 400; k ++ ){
			for(int d = 1; d <= 400; d ++ ){
				dp[i][k][d] = min(dp[i][k][d], dp[i][k - 1][d]);
				dp[i][k][d] = min(dp[i][k][d], dp[i][k][d - 1]);
			}
		}
	}
	
	int seed;
	cin>>seed;
	std::mt19937 rng(seed);
	std::uniform_int_distribution<> u(1,400);
	
	qq[0] = 1;
	for(int i = 1; i <= m; i ++ ){
		qq[i] = (qq[i - 1] * seed) % mod;
	}
	
	int lastans=0;
	for (int i=1;i<=m;i++)
	{
	    int IQ=(u(rng)^lastans)%400+1;  // The IQ of the i-th friend
	    int EQ=(u(rng)^lastans)%400+1;  // The EQ of the i-th friend
	    int AQ=(u(rng)^lastans)%400+1;  // The AQ of the i-th friend
	    lastans=solve(IQ,EQ,AQ);  // The answer to the i-th friend
	    ans = (ans + lastans * qq[m - i]) % mod;
	}
	cout<<ans<<endl;
	return 0;
} 

H Wall Builder II

这一题的铺砖的思路可以好好学学,还有长宽越接近,面积一定的矩形边长最短这个结论
请添加图片描述

#include<bits/stdc++.h>

using namespace std;

const int N = 110;

int T;
int n;
int s, y, x;
int a[N];

int main()
{
	cin>>T;
	while(T -- ){
		cin>>n;
		
		memset(a, 0, sizeof a);
		s = 0, x = 0, y = 0;  //初始化大矩形的长宽 
		
		for(int i = 1; i <= n; i ++ ){
			s += i * (n - i + 1);  //记录面积,宽度为1,长度*数量 
			a[i] = n - i + 1;  //长度为i的木板有(n - i + 1)块 
		}
		
		for(int t = 1; t * t <= s; t ++ ){
			if(s % t == 0) y = t;  //y记录最多铺几层 
		} 
		
		x = s / y;  //每一层最多铺多长
		int sl = 2 * x + 2 * y;  //周长 
		cout<<sl<<endl;
		
		for(int i = 1; i <= y; i ++ ){  //一层一层铺
			int cur = 0;  //每一层的起点从最左端开始,记录铺的砖块的左端 
			for(int k = n; k >= 1; k -- ){  //枚举这一块砖的宽度,从大往小铺 
				while(a[k] && x - cur >= k){  //长度为k的砖块剩余数量不为0,且这一层剩余长度大于这个长度k 
					cout<<cur<<' '<<i - 1<<' '<<cur + k<<' '<<i<<endl;
					cur += k;
					a[k] -- ; 
					if(cur == x) break;
				}
			} 
		}
	}
	return 0;
}

K NIO’s Sword

请添加图片描述

#include<bits/stdc++.h>

using namespace std;

#define int long long 

const int N = 1e6 + 10;

int n;
int ans;
int pool[10];

signed main()
{
	cin>>n;
	pool[0] = 1;
	for(int i = 1; i < 10; i ++ ) pool[i] = pool[i - 1] * 10;
	
	if(n == 1){
		puts("0");
		return 0;
	}
	
	//并不需要真的找出具体方案,只需要判断哪个区间内有这个值就可以
	//x是任意的,且x的变化不算在步数内,因此只要找到范围即可 
	
	for(int i = 1; i <= n; i ++ ){
		for(int j = 1; j <= 7; j ++ ){
			int l = (i - 1) * pool[j], r = i * pool[j] - 1;  //注意左右边界 
			if(r - l + 1 >= n){
				ans += j;
				break;  //这个步数已经找到,直接开始匹配下一个i 
			} 
			r %= n;
			l %= n;
			if(r > l){
				if(i % n >= l && i % n <= r){  //余数在这个范围,说明只需要变换x就能找到同余的数 
					ans += j;
					break;  //这个步数已经找到,直接开始匹配下一个i 
				}
			}
			else{
				if(i % n <= r || i % n >= l){  //i%n的余数在这个范围之内,说明还是可以构造出来 
					ans += j;
					break;  //这个步数已经找到,直接开始匹配下一个i 
				}
			}
		}
	}
	cout<<ans<<endl;
	
	return 0;
}

N Particle Arts

比赛是想出思路了,但是竟然莫名其妙过不去,可能是因为1e5n的n三次方爆了,但是long long明明可以存下这么多,我不理解

请添加图片描述

#include<bits/stdc++.h>

using namespace std;

#define int long long 
#define db double

const int N = 1e5 + 10;

int n;
int a[N];
int cnt[20];  //记录第i位有几个1,从右往左排n~1 

int get_wei(int x){
	int res = 0;
	while(x){
		res ++ ;
		x >>= 1;
	}
	return res;
}

int get_er(int x, int y){  //x这个数有y位二进制数 
	int res = 0;
	for(int i = 1; i <= y; i ++ ){
		if(x & 1){
			res ++ ;
			cnt[i] ++ ;
		} 
		x >>= 1; 
	}
	return res;
}

int tui(int iu){  //填充1 
	int res = 0;
	for(int i = iu; i >= 1; i -- ){
		if(cnt[i]){
			res ++ ;
			cnt[i] -- ;
		}
		res <<= 1;
	}
	
	res >>= 1;

	return res;
}

int gcd(int a, int b){
	if(b) return gcd(b, a % b);
	else return a;
}

int li;  //记录1的个数 
int iu;  //最高位有几位 
int sum;  //计算数值和
int ans1, ans2;
int sut;

signed main()
{
	cin>>n;
	
	for(int i = 0; i < n; i ++ ){
		scanf("%lld", &a[i]);
		sum += a[i];
		int r = get_wei(a[i]);
		iu = max(iu, r);  //记录最高位数  
		li += get_er(a[i], r);  //累加1的个数 
	}
	//sum已记录 
	for(int i = 0; i < n; i ++ ){  //填充n个数
		int t = tui(iu);
		ans1 += t * t;
		sut += sum * t;
	}
	
	ans1 *= n;
	ans1 += sum * sum;
	ans1 -= 2 * sut;
	
	ans2 = n * n;
	
	int ou = gcd(ans1, ans2);

	if(ou > 1){
		ans1 /= ou;
		ans2 /= ou;
	}
	
	//最小公倍数*最大公约数=a*b 
	//最小公倍数=ans1*n/最大公约数
    
	if(ans1 == 0) cout<<"0/1"<<endl;
	else cout<<ans1<<"/"<<ans2<<endl;
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值