首页 > 其他分享 >【解题报告】THOI2023核心素养一题解

【解题报告】THOI2023核心素养一题解

时间:2024-03-12 18:23:53浏览次数:36  
标签:int 题解 ll THOI2023 long 解题 奶牛 dp define

THOI核心素养一题解

展开目录

目录

比赛页面(题目已公开,邀请码:yspm)

赛时公告板

看得出来出了相当多锅(

由于 D 出锅严重,现已撤下,比赛延长 10min.还请各位海涵(

为什么延长 10min:18:25 吃饭(

比赛结果:

题目编号 题目名称 预计通过人数 实际通过人数
A \(\color{skyblue}\text{沙粒的记忆}\) \(7\) \(6\)
B \(\color{blue}\text{远星的守望}\) \(7\) \(1\)
C \(\color{purple}\text{国王的诞生}\) \(7\) \(4\)
E \(\color{#FFBB50}\text{坏齿的舞曲}\) \(2\) \(0\)
F \(\color{#B0DDAA}\text{山麓的回音}\) \(2\) \(0\)
EXTRA \(\color{#FF5500}\text{群星的闪耀}\) \(-\) \(-\)

A 沙粒的记忆

因为给出的数字和指数都是整数,所以指数只能是自然数(不小于 \(0\) 的整数)。

分析数据可知,在 \(a_i \le 10^{18}\) 的情况下,\(a_i\) 的各位数字之和最大是 \(9 \times 17\), 远小于 \(37^2\), 所以只需要判断 \(a_i\) 的各位数字之和是否等于 \(37^0\) 或 \(37^1\) 即可。时间复杂度 \(O(18 \cdot T\cdot N)\), 不过时限给得非常宽松,所以放过去了大部分没有优化的做法(

欢迎来暴踩标算:

image

展开代码
#include <bits/stdc++.h>
#define ll long long
#define MyWife Cristallo
using namespace std;
ll T, n, a, ans;
int main() {
	//freopen("THOI03A10.in", "r", stdin);
	//freopen("THOI03A10.out", "w", stdout); 
	scanf("%lld", &T);
	while(T--) {
		scanf("%lld", &n);
		while(n--) {
			scanf("%lld", &a);
			int x = 0;
			while(a != 0) {
				x += a % 10;
				a /= 10;
				if(x > 37) break;
			}
			if(x == 1 || x == 37) ++ans;
		}
		printf("%lld\n", ans);
		ans = 0;
	}
	return 0;
}

B 远星的守望

经典的斐波那契数列(繁殖兔子问题),只不过换成了重返版

在以下内容中,我们称已经开始复制的奶牛为处于分裂期的奶牛。

不难看出,第 \(N-2\) 天的奶牛只有三种情况:已经进入分裂期的奶牛、将在第 \(N-1\) 天进入分裂期的奶牛和将在第 \(N\) 天进入分裂期的奶牛。

因此,当第 \(N\) 天时,第 \(N-2\) 天的奶牛全都已经处于了分裂期,并在这一天分裂出了一只奶牛。

所以第 \(N\) 天的奶牛数就是第 \(N-2\) 天的奶牛数(新分裂的奶牛)加上第 \(N-1\) 天的奶牛数(已经有的奶牛)。

得到递推式:

\[F(N) = F(N-1) + F(N-2) \]

其中 \(F(0) = 0,F(1) = 1\), 因为第 \(0\) 天你还没有收到奶牛呢

展开代码
#include <bits/stdc++.h>
#define ll long long
#define MyWife Cristallo
using namespace std;
const int N = 105; 
ll T, x, y, f[N];
int main() {
	//freopen("THOI03B10.in", "r", stdin);
	//freopen("THOI03B10.out", "w", stdout); 
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d", &x, &y);
		f[1] = 1;
		for(int i = 2; i <= x; ++i) f[i] = f[i - 1] + f[i - 2];
		printf("%lld\n", f[x] - f[y]);
	}
	return 0;
}

C 国王的诞生

削了两次,现在已经是板上板了,call me 柏林以东(

01 背包板子。注意因为只要达到 \(M\) 就会昏厥,所以内层循环 j > w[i].

展开代码
#include <bits/stdc++.h>
#define ll long long
#define MyWife Cristallo
using namespace std;
const int N = 1e5 + 5;
ll n, m, x[N], y[N], dp[N]; 
int main() {
	//freopen("THOI03C10.in", "r", stdin);
	//freopen("THOI03C10.out", "w", stdout);
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i) scanf("%d%d", x + i, y + i);
	for(int i = 1; i <= n; ++i) for(int j = m; j > y[i]; --j) dp[j] = max(dp[j], dp[j - y[i]] + x[i]);
	printf("%d\n", dp[m]); 
	return 0;
}

E 坏齿的舞曲

要求奶量溢出最小,即已损失生命之和在不超过治疗量的情况下最大。考虑 01 背包。治愈一个小朋友的代价和收益都是这个小朋友的已损失生命。接下来考虑怎么记录治愈小朋友的个数。

可以把 dp 数组增开一维,大小为 \(2\), 使 \(dp_{j,0}\) 表示当前消耗的治疗量,\(dp_{j,1}\) 表示消耗 \(dp_{j,0}\) 点治疗量时,可以治愈的小朋友。于是有:

\[ dp_{j,0} = \left\{ \begin{array}{} dp_{j-w_i,0} + w_i & &dp_{j-w_i,0} > dp_{j,0}\\ dp_{j-w_i,0} + w_i & &dp_{j-w_i,0} \le dp_{j,0} \end{array} \right. \]

\[ dp_{j,1} = \left\{ \begin{array}{} dp_{j-w_i,1} + 1 & &dp_{j-w_i,0} > dp_{j,0}\\ dp_{j-w_i,1} + 1 & &dp_{j-w_i,0} \le dp_{j,0} \end{array} \right. \]

展开代码
#include <bits/stdc++.h>
#define ll long long
#define MyWife Cristallo
using namespace std;
const int N = 1e5 + 5;
ll n, m, x[N], dp[N][2]; 
int main() {
//	freopen("THOI03F20.in", "r", stdin);
//	freopen("THOI03F20.out", "w", stdout);
	scanf("%d%d", &n, &m); m *= 6;
	for(int i = 1; i <= n; ++i) scanf("%d", x + i);
	for(int i = 1; i <= n; ++i) for(int j = m; j >= x[i]; --j) if(dp[j - x[i]][0] + x[i] > dp[j][0]) dp[j][0] = dp[j - x[i]][0] + x[i], dp[j][1] = dp[j - x[i]][1] + 1;
	printf("%d\n", dp[m][1]); 
	return 0;
}

F 山麓的回音

因为只有一条路,所以可以搜索出路径,把所消耗的体力记作 \(V\), 所遇事件封进一个结构体加进 vector 里,最后对这个 vector 跑一个体积为 \(N-V\) 的 01 背包即可。

顺带一提,这个题全输出 \(0\) 可以拿 \(60pts\).

才不会告诉你们只有一条路是因为有多条我不会

展开代码
#include <bits/stdc++.h>
#define ll long long
#define MyWife Cristallo
using namespace std;
struct task {
	int a, b;
} d[105][105];
int n, m, h, x, y, c[105][105], v, dp[1005]; 
bool vis[105][105];
vector<task> e;
void dfs(int dx, int dy) {
	if(dx < 1 || dx > n || dy < 1 || dy > m) return;
//	cerr << dx << " " << dy << endl;
	if(c[dx][dy] == -1) return;
//	cerr << dx << " " << dy << endl;
	if(vis[dx][dy]) return;
	vis[dx][dy] = 1;
//	cerr << dx << " " << dy << endl;
	if(v + c[dx][dy] > h) return;
//	cerr << dx << " " << dy << endl;
//	cout << d[dx][dy].a << " " << v << endl;
	v += c[dx][dy];
	e.push_back(d[dx][dy]);
	if(dx == x && dy == y) return;
	dfs(dx - 1, dy);
	dfs(dx, dy - 1);
	dfs(dx + 1, dy);
	dfs(dx, dy + 1);
}
int main() {
//	freopen("THOI03E05.in", "r", stdin);
//	freopen("THOI03E05.out", "w", stdout);
	scanf("%d%d%d", &n, &m, &h);
	for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) scanf("%d", &d[i][j].a);
	for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) scanf("%d", &d[i][j].b);
	for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) scanf("%d", &c[i][j]);
//	cout << c[1][2] << endl;
	scanf("%d%d", &x, &y);
//	e.push_back({-1, -1});
//	cout << n << " " << m << endl;
	dfs(n, m);
//	cerr << "Antipathy world.\n";
	for(int i = 1; i < e.size(); ++i) {
		for(int j = h - v; j > e[i].b; --j) dp[j] = max(dp[j], dp[j - e[i].b] + e[i].a);
//		cerr << e[i].a << " " << e[i].b << " a\n";
	}
	printf("%d\n", dp[h - v]); 
	return 0;
}

EXTRA 群星的闪耀

image

标签:int,题解,ll,THOI2023,long,解题,奶牛,dp,define
From: https://www.cnblogs.com/Kiichi/p/18068645/THOI20230312-test

相关文章

  • 【计算机网络01】网卡——链接5G热点网速较慢问题解决方法。
    计算机网络:网卡一、网卡带宽查询二、高速带宽设置一.在电脑连接手机热点的时候,查询网络属性,找到网络频带是2.4GHz,带宽是72(Mbps):查找原因,发现是手机热点页面中AP频带设置的原因,AP频带设置成了2.4GHz:二.更改手机热点页面中AP频带,将AP频带设置成了5GHz频段:再在电......
  • Dwango Programming Contest 6th D 题解
    正好测试一下专栏的题解系统。我省选寄了都怪洛谷/fn/fn/fn/fn/fn/fn/fn题解显然可以对于所有关系建有向边,显然是基环外向树森林。由于是字典序最小,因此找到最小的上一个点没有直接连向边的点一定最优。但是有时取最优会导致最后无法选完,我们考虑无法选完的情况。第一种是......
  • AtCoder Beginner Contest 344 A-G 题解
    AtCoderBeginnerContest344A-SpoilerQuestion删除两个|之间的字符Solution按照题意模拟即可Code#include<bits/stdc++.h>usingnamespacestd;intmain(){strings;cin>>s;stringp1,p2;for(inti=0;i<s.size();i++){......
  • LeetCode - 高频SQL50题(基础版)部分题解(上)
    1581.进店却未进行过交易的顾客原题:https://leetcode.cn/problems/customer-who-visited-but-did-not-make-any-transactions/题意:有一些顾客可能光顾了购物中心但没有进行交易。请你编写一个解决方案,来查找这些顾客的ID(customer_id),以及他们只光顾不交易的次数(count_no_trans......
  • node: /lib64/libm.so.6: version `GLIBC_2.27‘ not found问题解决方案
    场景centos7服务器使用nvm安装的node之后,只要使用npm或者node,均会出现以下问题。npm-vnode:/lib64/libm.so.6:version`GLIBC_2.27'notfound(requiredbynode)node:/lib64/libc.so.6:version`GLIBC_2.25'notfound(requiredbynode)node:/lib64/libc.so.6:ver......
  • 开摆题解
    开摆--更新ing没有详解(大概目录开摆--更新ingA题B题C题D题E题A题不配文字讲解了,具体的直接问我本人吧前缀和视频C++代码voidsolve(){intn,m,w,x,i,ans=0;cin>>n;vector<int>qwq(49);//前缀和数组for(i=0;i<n;++i){cin>......
  • rosdep update超时问题解决
    此问题的解决也适用ros11、初始化$sudorosdepinit2、下载rosdistro到本地$gitclonehttps://github.com/ros/rosdistro.git3、修改以下文件,将其url指向本地(1)文件1:20-default.list地址路径:/etc/ros/rosdep/sources.list.d/20-default.list原来内容:#os-specificl......
  • 随机逆序对 题解
    题意给定$1\simn$的排列$a_{1...n}$。在上面进行依次如下操作:首先在$[1,n]$​中选取一个子序列(可以为空);然后将这个子序列内的数重新排列。两个操作不同,当且仅当选取的子序列不同或者重新排列的方式不同。对于所有不同的操作,求他们产生的排列的逆序对个数和,答案......
  • 【蓝桥-大试牛刀7-最短路专场】题解
    最短路1floyd说白了就是个暴力,用三层循环枚举所有路径,然后留下权值最小的一条大概就长这个样for(中转点k) for(起点i) for(终点j) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);注意这个题的数据有重边,输入的时候留下最小的,这样就做完了intd[N][N];voidsolve(){......
  • LeetCode 128.最长连续序列 Python题解
    leetcode128题最长连续序列分享解题思路,使用哈希表算法......