CSDN竞赛4期题解

总结

csdn的竞赛,与其他OJ的周赛相比,有些不太好的体验。举个例子,T1只是想分段收个电费,150度以下的怎么收费,151度以上的怎么收费,按照表述151度电就只收150度的电费,因为没说150-151度之间怎么收费了;T2虽然题目没啥毛病,但是给句子中单词逆序,本来需要做些操作的,cpp给定的模板直接将每个单词存入vector了,要做的就是给vector倒着取下数,没啥意义。T3一开始给的唯一一个用例是3 3,结果是10,给3拆分成3个不小于1的整数,有10种拆法,后面刷新修正为1,用例出错不说什么了。如果给4分为两个整数,那么1 3和3 1算一种还是两种题目也没有表述清楚;T4就是像求个最小的修改数量是多少,问的是通过修改最小的数字变成美丽数列,很容易误解为只能改最小的数字。希望后面的竞赛能改掉这些不足的地方吧。

下面题解代码为赛后书写,所以还不能保证能够通过评测,如果有问题,还望各位大佬帮忙指正。

题目列表

1.小玉家的电费

题目描述

夏天到了,各家各户的用电量都增加了许多,相应的电费也交的更多了。小玉家今天收到了一份电费通知单。小玉看到上
面写:据闽价电[2006]27号规定,月用电量在150千瓦时及以下部分按每千瓦时0.4463元执行,月用电量在151~400
千瓦时的部分按每千瓦时0.4663元执行,月用电量在401千瓦时及以上部分按每千瓦时0.5663元执行;小玉想自己验证一
下,电费通知单上应交电费的数目到底是否正确呢。请编写一个程序,已知用电总计,根据电价规定,计算出应交的电费
应该是多少。

分析

首先忽略题目不恰当的表述,重新理解为150以下电费多少,150-400电费多少,400以上电费多少,然后分类讨论下即可。

代码

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
	float n;
	cin>>n;
	float res = 0;
	if(n <= 150)	res += n * 0.4463;
	else {
		res += 150 * 0.4463;
		if(n <= 400)	res += (n - 150) * 0.4663;
		else {
			res += 250 * 0.4663 + (n - 400) * 0.5663;
		}
	}
	printf("%.1f\n",res);
	return 0;
} 

2.单词逆序

题目描述

对于一个字符串,请设计一个算法,只在字符串的单词间做逆序调整,也就是说,字符串由一些由空格分隔的部分组成,
你需要将这些部分逆序。 给定一个原字符串A,请返回逆序后的字符串。例,输入”I am a boy!“输出”boy! a am I“

分析

题目输入模板已经帮我们分割了单词,逆序输出即可。

代码

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
std::vector<std::string> solution(std::vector<std::string>& vec){
	std::vector<std::string> result;
	int n = vec.size();
	for(int i = n - 1;i >= 0;i--)	result.push_back(vec[i]);
	return result;
}
int main() {
	std::vector<std::string> vec;
	std::string line_0, token_0;
	getline(std::cin >> std::ws,line_0);
	std::stringstream tokens_0(line_0);
	while(std::getline(tokens_0, token_0, ' ')){
		vec.push_back((token_0));
	}
	std::vector<std::string> result = solution(vec);
	for(auto it=result.begin();it!=result.end();++it){
		std::cout<<*it<<" ";
	}
	std::cout<<std::endl;
	return 0;
}

3.小Q整数分割

题目描述

小Q决定把一个整数n,分割为k个整数。 每个整数必须大于等于1。 小Q有多少方案。

分析

举个例子,如果将4分割为2个正整数,1 3和3 1算不同的方案数的话,那么只需要考虑简单的组合数问题。也就是等价于有一个长度为n的线段,要将这条线段切成k段,就需要在线段上找k - 1个切点,一共有C(n - 1,k - 1)种切法,这个组合数就是答案。

但是本题实际的含义将1 3和3 1视为不同的方案,这个就有点难度了。可以理解为在1到n中找k个正整数,使得这k个正整数之和等于n的方案数。然后问题就变成了方案里面1选了多少个,2选了多少个,…。就可以使用背包问题的思想来解决本题了。

状态表示:f[i][j][t]表示1到i中选了t个整数,且这t个整数的和是j的方案数。t个整数的和可以理解为背包问题中的体积,t相当于附加的限制条件。

状态边界:f[i][0][0] = 1表示前i个整数中一个不选的方案数。

状态转移:需要考虑i这个整数选了几次,选的次数可以是0, 1, 2, …, r次,那么状态转移方程为f[i][j][t] = sum(f[i-1][j-i*r][t-r])。

复杂度分析:枚举i、j、r需要三重循环,而枚举i出现的次数还需要一重循环,本题的数据规模是100,O(n4)的复杂度就有点危险了,考虑使用背包问题类似的优化手段。

考虑f[2][8][4]这个状态转移的过程
2这个数字可以出现0到4次
f[2][8][4] = f[1][8][4] + f[1][6][3] + f[1][4][2] + f[1][2][1] + f[1][0][0]
再来看f[2][6][3]状态的转移过程
f[2][6][3] =              f[1][6][3] + f[1][4][2] + f[1][2][1] + f[1][0][0]
显然,f[2][8][4] = f[2][6][3] + f[1][8][4]

根据上面的例子我们可以得到优化后的状态转移方程:f[i][j][t] = f[i][j-i][t-1] + f[i-1][j][t]。这样一来时间复杂度降到了立方级别,106的计算次数是完全可以接受的。由于每个状态只用到了左边以及上一层相同的状态,所以可以使用滚动数组实现,去掉第一维状态。

代码

#include <iostream>
using namespace std;
const int N = 105, MOD = 1e9 + 7;
int n,k;
int f[N][N];
int main() {
	cin>>n>>k;
	f[0][0] = 1;
	for(int i = 1;i <= n;i++) {
		for(int j = i;j <= n;j++) {
			for(int t = 1;t <= k;t++) {
				f[j][t] = (f[j][t] + f[j - i][t - 1]) % MOD;
			}
		}
	}
	cout<<f[n][k]<<endl;
	return 0;
}

4.新型美丽数列

题目描述

定义美丽数列A: 1. 数列中相邻的数越是靠内相对大小加一,a[2]=a[1]+1,a[n-2]=a[n-1]+1… 2. 距离边缘距离相等的
数的大小相等:a[0] = a[n-1],a[1] = a[n-2]… 通过修改最小的数字使得给定数列变成美丽数列。 修改后的值必须仍是正
整数。
输入描述:
第一行输入整数n。(1<=n<=1000)表示数列的大小。
第二行输入n个整数。
输出描述:
输出最小修改。
输入样例:
3
1 1 1
输出样例:
1

分析

比赛时候想的是DFS和DP的思路,后面没时间就没作答了。比赛之后又看了下,分析出题目的隐藏条件,就很容易解决了。

首先,明确题意,题目表述不太清楚,我理解为数列有奇数个元素时,像1 2 3 2 1,除了中间数只有一个,其他数都是由内而外逐渐减去一的;数列有偶数个元素时,像1 2 2 1这种中间两个数是相等的,其他数由内而外减去一。然后给定若干个数列,判断要多少次操作才能将给定的数列转化为美丽数列。(PS:这么简单的表述,题目表述不清像是直接机器从英文题面翻译过来的。)

解题的关键在于一个性质,表面看是要修改很多元素才能变为美丽数列,实际只要确定了中间的数字,其他数字也就确定了。举个例子:

1 4 3 2 5

设中间的元素3改变为t,那么最终的数列就是t - 2,t - 1, t,t - 1,t - 2,来看下每个数字的改变量,分别是t - 3, t - 5, t - 3 - 1, t - 3, t - 7,现在希望改变的元素数量最少,也就是希望改变量数组中0的数量最多,而t是变量,意味着只要让改变量数组中出现最多的元素是0,那么就可以使得改变的元素数量最少,最后发现t - 3出现的次数最多,是3次,所以有三个位置元素不用改变,因此t取3最合适。

如果数列有偶数个元素呢,那么只需要设中间两个数改变为t即可。

具体在实现时,并不需要设变量t,只需要对最中间的数保持不变,由内而外每个数字一次加上1,2,3,…即可,比如1 4 3 2 5,处理后得到3 5 3 3 7,然后出现最多的数字就是3,所以最中间的数字取3,最后不等于3的数有2个,就是需要改变的数量。所以本题相当于给原数组做了下归一化之后求个哈希。

代码

#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N = 1005;
int n,a[N];
unordered_map<int,int> m;
int main() {
	cin>>n;
	for(int i = 0;i < n;i++)	cin>>a[i];
	int t = (n - 1) / 2;
	if(n & 1) {
		int k = 1;
		while(t - k >= 0) {
			a[t-k] += k;
			a[t+k] += k;
			k++;
		}
	}
	else {
		int k = 1;
		while(t - k >= 0) {
			a[t-k] += k;
			a[t+k+1] += k;
			k++;
		}
	}
	for(int i = 0;i < n;i++)	m[a[i]]++;
	int s = 0;
	for(auto x : m) {
		s = max(s,x.second);
	}
	cout<<n - s<<endl;
	return 0;
} 
} 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340