2023“钉耙编程”中国大学生算法设计超级联赛(2)

这篇具有很好参考价值的文章主要介绍了2023“钉耙编程”中国大学生算法设计超级联赛(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1001 Alice Game

题意:

起初有n个物品,玩家可以有如下操作:
①若该堆物品数量小于等于k,全部拿走。
②若该堆物品数量大于k,则只能选择拿走k个物品,并将剩余物品分成不为空的两堆。
Alice先手,问谁必胜。

分析:

打表可知当n % (4 * k + 2) == k + 1时Alice必败,其他时候必胜。
2023“钉耙编程”中国大学生算法设计超级联赛(2)
打表代码:

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

typedef long long LL;
const int N = 1e6 + 5;
LL f[N];

int sg(int x, int k) {
	if (f[x] != -1)
		return f[x];
		
	set<int> S;
	
	if (x <= k && x > 0)
		S.insert(sg(0, k));
	else {
		for (int i = 2; i <= x - k; i ++) {
			S.insert(sg(i - 1, k) ^ sg(x - (i + k - 1), k));
		}	
	}
	
	for (int i = 0;; i ++) {
		if (S.count(i) == 0)
			return f[x] = i;
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	
	int k = 3;
	for (int i = 1; i <= 100; i ++) {
		memset(f, -1, sizeof f);
		cout << sg(i, k) << " ";
		if (i % (4 * k + 2) == 0)
			cout << endl;
	}

	return 0;
}

代码:

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

int main() {
	std::ios::sync_with_stdio(false); 
	cin.tie(0), cout.tie(0);
	
	int t;
	cin >> t;
	
	while (t --) {
		int n, k;
		cin >> k >> n;
		
		if ((n % (4 * k + 2)) == k + 1)
			cout << "Bob" << endl;
		else
			cout << "Alice" << endl;
	}
	
	return 0;
}

1002 Binary Number

题意:

给定一个01串,有k次操作,每次选择一个区间将其翻转,求k次操作后的最大结果。

分析:

最高位一定是1。
①n = 1:k为奇数则输出0,k为偶数则输出1
②n > 1:设连续0的段数为m。显然要让结果最大,要尽可能将高位的0翻转。
k < m:则将前k端连续0翻转为1;
k ≥ m:特别的当m = 0,k = 1时将最后一位变为0。其他情况,我们先将m段0翻转为1,然后考虑对较低的位去操作,若k - m是偶数则翻转最后一位k - m次,因此不影响结果;若k - m是奇数可以先翻转最低位一次,再翻转次低位一次,然后将次低位和最低位一起翻转,剩下的操作为偶数不影响结果。综上除了特殊情况其他均输出n个1。

代码:

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

typedef long long LL;

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	
	int t;
	cin >> t;
	
	while (t --) {	
		int n;
		LL k;
		cin >> n >> k;
		
		string s;
		cin >> s;
		
		if (n == 1) {
			if (k & 1)
				cout << 0 << endl;
			else
				cout << 1 << endl;
			continue;
		}
		
		int cnt = 0;
		for (int i = 0; i < n;) {
			int j = i + 1;
			if (s[i] == '0') {
				while (j < n && s[j] == '0')
					j ++;
				cnt ++;
			}
			i = j;
		}
		
		if (k < cnt) {
			if (k == 0)
				cout << s;
			else {
				for (int i = 0; i < n;) {
					int j = i + 1;
					if (s[i] == '0') {
						if (k) {
							k --;
							cout << 1;
							while (j < n && s[j] == '0') {
								cout << 1;
								j ++;
							}
						} else
							cout << 0;
					} else
						cout << 1;
					i = j;
				}
			}
		} else {
			if (cnt == 0 && k & 1) {
				for (int i = 0; i < n - 1; i ++)
					cout << 1;
				cout << 0;
			} else {
				for (int i = 0; i < n; i ++)
					cout << 1;
			}
		}
		cout << endl;
	}		
	
	return 0;
}

1004 Card Game

题意:

给你n个堆,起初第一个堆放了k个东西,下面大上面小,其它堆都是空的,需要通过其它空堆的中转作用将k个东西从第一个堆全部放到第二个堆上(也是下面大上面小),问最多可以成功转移的k的个数是多少。

分析:

找规律。发现f[n] = f[n - 1] * 2 + 1 => f[n] = \(2^{n - 1}\) - 1。

代码:

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

typedef long long LL;
int mod = 998244353;

LL qmi(LL m, LL k) {
	LL res = 1, t = m;
	while (k) {
		if (k & 1)
			res = res * t % mod;
		t = t * t % mod;
		k >>= 1;
	}
	return res;
}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	
	int t;
	cin >> t;
	
	while (t --) {
		int n;
		cin >> n;
		
		cout << qmi(2, n - 1) - 1 << endl;
	}
	
	return 0;
}

1007 foreverlasting and fried-chicken

题意:

给你一个无向图,求出如下图形的数量。
2023“钉耙编程”中国大学生算法设计超级联赛(2)

分析:

枚举度大于等于6的点和度大于等于4的点,分别设为u,v。设与u相连的结点数为cnt,u和v均相连的结点数为cnt2,则u,v能组成的目标图形数为\(C_{cnt2}^4·C_{cnt - cnt2}^2\)。倘若暴力枚举cnt2会是\(O^3\)的复杂度,因此考虑用bitset优化。可以用bitset维护一个邻接矩阵g,cnt = g[u].count(),cnt2 = (g[u] & g[v]).count()。

代码:

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

typedef long long LL;
const int N = 1010, mod = 1e9 + 7;
bitset<N> g[N];
LL f[N], f2[N];

LL qmi(LL m, LL k) {
	LL res = 1, t = m;
	
	while (k) {
		if (k & 1)
			res = res * t % mod;
		t = t * t % mod;
		k >>= 1;
	}
	
	return res;
}

void init() {
	f[0] = f2[0] = 1;
	for (int i = 1; i < N; i ++) {
		f[i] = f[i - 1] * i % mod;
		f2[i] = f2[i - 1] * qmi(i, mod - 2) % mod;
	}
}

LL C(int a, int b) {
	if (a < b || b < 0)
		return 0;
	else
		return f[a] * f2[b] % mod * f2[a - b] % mod;
}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	
	int t;
	cin >> t;
	
	init();
	
	while (t --) {
		int n, m;
		cin >> n >> m;
		
		for (int i = 1; i <= n; i ++)
			g[i].reset();
		
		while (m --) {
			int a, b;
			cin >> a >> b;
			
			g[a][b] = g[b][a] = 1;
		}
		
		LL res = 0;
		
		for (int i = 1; i <= n; i ++) {
			for (int j = i + 1; j <= n; j ++) {		
				int cnt1 = g[i].count(), cnt2 = g[j].count();
				if (g[i][j])
					cnt1 --, cnt2 --;
				int cnt3 = (g[i] & g[j]).count();
				res = (res + C(cnt3, 4) * C(cnt1 - 4, 2) + C(cnt3, 4) * C(cnt2 - 4, 2)) % mod;
			}
		}
		
		cout << res << "\n";
	}
	
	return 0;
}

1009 String Problem

题意:

取k个子串,每个子串只包含一种字母,问子串长度之和减去k的最大值是多少。

分析:

双指针枚举满足条件的子串的最长长度,其对答案的贡献为子串长度减1。

代码:

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

const int N = 27;

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	
	int t;
	cin >> t;
	
	while (t --) {	
		string s;
		cin >> s;
		
		int res = 0;
		for (int i = 0; i < s.size();) {
			int j = i + 1;
			while (j < s.size() && s[j] == s[i])
				j ++;
			res += j - i - 1;
			i = j;
		}
		
		cout << res << endl;
	}		
	
	return 0;
}

1010 Klee likes making friends

题意:

给定n个元素,每个元素有一个权值,要求每连续m个元素至少要有两个元素被选,求所选元素权值之和的最小值。

分析:

考虑dp。
f[i][j]表示所选方案中最后一个在i倒数第二个在j的权值之和的最小值,且i - j < m。由于[j,i]之间没有元素被选,因此倒数第三个所选的元素k应当在[i - m, j - 1]内。f[i][j] = a[i] + min(f[j][k]), k∈[i - m, j - 1]。 min(f[j][k])可以通过在递推时维护一个后缀最小值来处理。我们可以预处理前m个元素,然后递推,最后对在[n - m + 1, n]内的所有f[i][j]取个min就是答案。
但这样定义状态i×j最大有1e8级别,会MLE。考虑优化,首先很容易想到j可以用相对距离i - j来描述。其次,由于我们每次考虑一个长度为m的区间,因此第一维可以用i % m表示。新的状态可以定义为:f[k][l]表示所选方案中最后一个元素所在位置为k(k = i % m)倒数第二个元素与倒数第一个元素的相对距离为l(l = i - j)的权值之和的最小值。

代码:

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

const int N = 2010, M = 20010;
int f[N][N], Min[N][N], pos[M];
int a[M];

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	
	int t;
	cin >> t;
	
	while (t --) {
		int n, m;
		cin >> n >> m;
		
		for (int i = 1; i <= n; i ++) {
			cin >> a[i];
			pos[i] = i % m;
		}
		
		for (int i = 0; i <= m; i ++) {
			for (int j = 0; j <= m; j ++) {
				f[i][j] = Min[i][j] = 0x3f3f3f3f;
			}
		}
		
		for (int i = 2; i <= m; i ++) {
			for (int j = i - 1; j >= 1; j --) {
				f[pos[i]][i - j] = a[i] + a[j];
				Min[pos[i]][i - j] = min(Min[pos[i]][i - j - 1], f[pos[i]][i - j]);
			}
		}
		
		for (int i = m + 1; i <= n; i ++) {
			for (int j = i - 1; j >= i - m + 1; j --) {
				f[pos[i]][i - j] = a[i] + Min[pos[j]][j - (i - m)];
				Min[pos[i]][i - j] = min(Min[pos[i]][i - j - 1], f[pos[i]][i - j]); 
			}
		}
		
		int res = 0x3f3f3f3f;
		for (int i = n - m + 2; i <= n; i ++) {
			for (int j = i - 1; j >= n - m + 1; j --) {
				res = min(res, f[pos[i]][i - j]);	
			} 
		}
		
		cout << res << endl;
	}
	
	return 0;
}

1011 SPY finding NPY

题意:

n个人,IQ值为n的全排列,先取前k个人的最大IQ值m,之后从[k + 1, n - 1]位置内去选第一个大于m的人否则选第n个人,问选到IQ为n的概率最大时k的最小值。

分析:

设选到的人在位置a,且在[1, a - 1]内,IQ最大的人在[1, k]的概率:\(\frac{k}{n(a - 1)}\)。则选到IQ为n的概率为:\(\frac{1}{n}\sum_{i=k+1}^{n}{\frac{k}{(i - 1)}} = \frac{k}{n}\sum_{i=k}^{n-1}{\frac{1}{i}}\)。可以用前缀和预处理出\(\sum{\frac{1}{i}}\),然后枚举k取个min即可。文章来源地址https://www.toymoban.com/news/detail-607766.html

代码:

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

const int N = 1e4 + 5;
double f[N];

struct Ans {
	int k;
	double p;
};

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	
	int t;
	cin >> t;
	
	while (t --) {
		int n;
		cin >> n;
		
		memset(f, 0, sizeof f);
		
		for (int i = 1; i <= n; i ++)
			f[i] = f[i - 1] +  1.0 / i;
			
		Ans ans = {0, 1.0 / n};
		
		for (int k = 1; k < n; k ++) {
			double p2 = 1.0 * k / n * (f[n - 1] - f[k - 1]);
			if (ans.p < p2) {
				ans = {k, p2};
			}
		}
		
		cout << ans.k << endl;
	}
	
	return 0;
}

到了这里,关于2023“钉耙编程”中国大学生算法设计超级联赛(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (杭电多校)2023“钉耙编程”中国大学生算法设计超级联赛(4)

    1003 Simple Set Problem 双指针的思想,双端队列 先从小到大排个序 一个一个放到双端队列里,一边放一边维护集合个数为k个 利用滑动窗口,当滑动窗口中集合个数为k时,只需算出滑动窗口最后一个数减去第一个数,然后每次取min就行了 AC代码:  1006 PSO  两两组合 期望=所有组合的边

    2024年02月15日
    浏览(20)
  • 2023“钉耙编程”中国大学生算法设计超级联赛(1)Hide-And-Seek Game

    2023“钉耙编程”中国大学生算法设计超级联赛(1)Hide-And-Seek Game 题目大意 有一棵有 n n n 个节点的树,小 S S S 和小 R R R 在树上各有一条链。小 S S S 的链的起点为 S a S_a S a ​ ,终点为 T a T_a T a ​ ;小 R R R 的链起点为 S b S_b S b ​ ,终点为 T b T_b T b ​ 。 小 S S S 和小 R R

    2024年02月16日
    浏览(24)
  • 2023年度第四届全国大学生算法设计与编程挑战赛(春季赛)

     A 题目描述        有一个长为 n (1le n le 1000)n (1≤n≤1000) 的序列,序列上的元素两两不同。你需要用最少的操作步数翻转这个序列。        每次操作你需要给出三个数 i,j,k(1le ile j k le n)i,j,k(1≤i≤jk≤n),交换序列中下标属于 [i,j][i,j] 的元素与下标属于 [j+1,k][j+

    2024年02月08日
    浏览(45)
  • 2023年天府杯全国大学生数学建模竞赛B题中国环境问题的治理解题全过程

       问题背景:    随着经济的快速发展和人口的持续增长,中国的环境问题已经成为了一个急需解决的重要问题。这些环境问题不仅对人们的健康和生活质量产生了巨大的影响,还对生态系统和生态平衡造成了极大的破坏。近年来,中国政府积极推动环保事业的发展,通

    2024年02月08日
    浏览(17)
  • 2023年四川大学生程序设计竞赛-K.倒转乾坤

    Cuber QQ 现在手上有两个圆环,其中小圆环的直径是 d,大圆环的直径是 2d 。他将小圆环放在大圆环内, 并让小圆环紧贴大圆环内壁进行无滑动的滚动。   Cuber QQ 总是喜欢动态的美,他在小圆环上等间隔地标记了 n 个点,他想知道在小圆环贴着大圆环运动一周后,他所

    2024年02月16日
    浏览(31)
  • 【电子设计大赛】2023 年全国大学生电子设计竞赛 仪器和主要元器件清单

    1. 仪器设备清单 直流稳压电源(具有恒流/恒压模式自动切换功能,0~30V/3A,双路) 数字示波器(100MHz, 双通道) 函数发生器(50 MHz,双通道) 射频信号源(500MHz,-100dBm~0dBm,具有射频输出开关功能) 矢量网络分析仪(1GHz) 频谱分析仪(1GHz) 频率计(500MHz) 功率分析仪

    2024年02月15日
    浏览(25)
  • 2023 年第五届河南省 CCPC 大学生程序设计竞赛

    Problem A. 小水獭游河南 ∣ a ∣ ≤ ∣ Σ ∣ = 26 ,暴力枚举 a 判断 b 是否为是回文串即可,时间复杂度 O ( ∣ Σ ∣ ∣ s ∣ ) 。 |a| ≤ |Σ| = 26,暴力枚举 a 判断 b 是否为是回文串即可,时间复杂度 O(|Σ||s|)。 ∣ a ∣ ≤ ∣Σ∣ = 26 ,暴力枚举 a 判断 b 是否为是回文串即可,时间复

    2024年02月03日
    浏览(49)
  • 2023年第十五届“中国电机工程学会杯”全国大学生电工数学建模竞赛题目 A题:电采暖负荷参与电力系统功率调节的技术经济分析

    建设以新能源为主体的新型电力系统是应对全球气候变化挑战的重要举措。高比例新能源接入导致电力系统调节能力稀缺,亟需开发新的调节资源,如火电深度调峰、建设抽水蓄能电站、配置储能和挖掘负荷中的调节能力等。现代电力负荷中含有较大比重的温控型负荷(如空

    2024年02月06日
    浏览(24)
  • 【毕业设计】基于springboot的大学生综合素质测评系统——2023最新推荐

    【毕业设计】基于springboot大学生综测管理系统 🥇 个人主页 :@MIKE笔记 🥈 文章专栏 :毕业设计源码合集 ⛄ 联系博主: wx: mikenote 项目名 文章地址 💹下载 基于springboot的 大学生综合素质测评管理系统 http://t.csdn.cn/smVjL v1.0 // v2.0 基于springboot + vue 微信小程序文创平台商城

    2024年02月06日
    浏览(22)
  • 第五届湖北省大学生程序设计竞赛(HBCPC 2023)vp赛后补题

    思路: 数位dp,如果我们暴力的计算的状态的话,显然就是记录每个数字出现几次。但是显然这样难以发挥数位dp的记忆化功效,因为只有出现次数相同,你是什么数字,实际是无所谓的。所以我们尝试记录每个出现次数有多少个数字 尝试打表发现,结果只有1477种 所以,对

    2024年02月07日
    浏览(17)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包