IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Codeforces Round #740 (Div. 2 based on VK Cup 2021 - Final (Engine)) (A~D1)题解 -> 正文阅读

[C++知识库]Codeforces Round #740 (Div. 2 based on VK Cup 2021 - Final (Engine)) (A~D1)题解

比赛链接

官方题解链接


1561A Simply Strange Sort 题目链接:点击这里传送

在这里插入图片描述
题意:
现给出一串序列,要将其变成升序。关于一趟排序的定义是

for (int i = 1; i <= n-2; i += 2)
{
	if (a[i] > a[i + 1]) swap(a[i], a[i + 1]);
}

或者

for (int i = 2; i <= n-1 ; i += 2)
{
	if (a[i] > a[i + 1]) swap(a[i], a[i + 1]);
}

问最少要几趟。
思路:
题目咋说就咋做

#include<bits/stdc++.h>
using namespace std;
#define MAXN 1005
int a[MAXN];
int n, t;
bool check()
{
	for (int i = 1; i <= n; i++)
	{
		if (a[i] != i) return 0;
	}
	return 1;
}
int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> t;
	while (t--)
	{
		memset(a, 0, sizeof(a));
		cin >> n;
		int cnt = 0;
		for (int i = 1; i <= n; i++) cin >> a[i];
		while (1)
		{
			if (check() == 1) break;
			for (int i = 1; i <= n-2; i += 2)
			{
				if (a[i] > a[i + 1]) swap(a[i], a[i + 1]);
			}
			cnt++;
			if (check()==1) break;
			for (int i = 2; i <= n-1 ; i += 2)
			{
				if (a[i] > a[i + 1]) swap(a[i], a[i + 1]);
			}
			cnt++;
		}
		cout << cnt << endl;
	}

	return 0;
}

1561B Charmed by the Game 题目链接:点击这里传送

在这里插入图片描述
题意:
给出一场乒乓球比赛的最终得分,求出所有可能的破发球情况。
思路:
第一视角解说
破发球次数=我方破发球次数+我方被破发球次数
总得分为偶数,我方发球次数=sum ÷ \div ÷ 2
总得分为奇数,我方发球次数=sum ÷ \div ÷ 2或者sum ÷ \div ÷ 2+1。
我方破发球次数=我方得分-我方成功发球次数
我方被破发球次数=我方发球次数-成功发球次数
我方得分已知,我方发球次数已知,只需枚举我方成功发球次数即可。
需要注意的是,我方得是得分少的那个,这样才能确保成功发球次数。如果用得分多的,假设他的分数超过了我方发球次数,那么就不能通过 [ 0 , 我 方 得 分 ] \left[0,我方得分\right] [0,]来枚举我方发球成功次数了。

#include<bits/stdc++.h>
using namespace std;
set <int> s;
int n, m,t;
int sum;

int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> t;
	while (t--)
	{
		s.clear();
		cin >> n >> m;
		sum = n + m;
		if (n > m) swap(n, m);
		//破发球次数=我方破发球次数+我方被破发次数
		//我方破发球次数=我方分数-发球成功次数   n-i
		//我方被破发次数=发球总数-成功发球次数	  sum/2-i或sum/2+1-i
		//发球次数 偶数 sum/2 奇数sum/2+1或sum/2  枚举发球成功次数
		if (sum % 2 == 0)
		{
			for (int i = 0; i <= n; i++) s.insert(n - i + sum / 2 - i);
		}
		else
		{
			for (int i = 0; i <= n; i++)
			{
				s.insert(n - i + sum / 2 - i);
				s.insert(n - i + sum / 2 + 1 - i);
			}
		}
		cout << s.size() << endl;
		for (auto x : s) cout << x << " ";
		cout << endl;
	}
	return 0;
}

1561C Deep Down Below 题目链接:点击这里传送

在这里插入图片描述
题意:
你是一名战士,你要去打怪升级。你有初始攻击力为n点,假设怪物有m点护甲值,只有当n>m时才能打得过怪并且获得+1攻击力,否则你就死了。现在你要去刷副本,一个副本内必须按照给定的怪物顺序一个一个杀过去。你可以任意挑选挑战副本的顺序。现在你有一个修改器,可以调整初始攻击力,问最少需要多少初始攻击力才能打通所有副本。
思路:
设一个副本内怪物的攻击力为 a i a_i ai?,需要
a 1 + 1 a_{1}+1 a1?+1, a 2 + 1 ? 1 a_{2}+1-1 a2?+1?1, a 3 + 1 ? 2 a_3+1-2 a3?+1?2+……+ a n + 1 ? ( n ? 1 ) a_n+1-(n-1) an?+1?(n?1)点攻击力。把这其中最高的攻击力拿出来就是通关这个副本需要的最小攻击力,设他为 b i b_i bi?
将b数组进行升序排序。进行模拟找出通关所有副本的最小初始攻击力。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int t, n,m;
#define MAXN 100005
ll a[MAXN];//临时处理数据用
struct node
{
	ll val;//打通副本需要的最小初始攻击力
	int num;
}b[MAXN];
bool cmp(node a, node b) { return a.val < b.val; }
int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> t;
	while (t--)
	{
		cin >> n;
		for (int k = 1; k <= n; k++)//初始攻击力要尽可能小
		{
			cin >> m;
			ll temp = 0;
			for (int i = 1; i <= m; i++)
			{
				cin >> a[i];
				a[i] = a[i] - (i - 1);
				temp = max(temp, a[i]+1);
			}
			//cout << "进这个本需要" << " " << temp << endl;
			b[k].val = temp;
			b[k].num = m;
		}
		sort(b + 1, b + 1 + n,cmp);//从易到难给副本难度排序
		ll ans = 0;
		ll num = 0;
		ll current_attack = 0;
		for (int i = 1; i <= n; i++)
		{
			if (current_attack >= b[i].val)
			{
				current_attack += b[i].num;
				//cout << current_attack << ">=" << b[i].val << endl;
			}
			else//攻击力不够,要更新ans
			{
				//cout << "需要" << b[i].val << "初始力量,减去" << num << endl;
				ans = ans + (b[i].val - current_attack);
				current_attack = b[i].val+b[i].num;
			}
			num += b[i].num;
		}
		cout << ans << endl;
	}
	return 0;
}

1561D1 Up the Strip (simplified version) 题目链接:点击这里传送

在这里插入图片描述
题意:
有一个数n,你要将他变成1.你可以把他变成n/2,也可以将他变成n-1,求有多少种操作的方法能将n变为1.
思路:
设dp [ i ] \left[i\right] [i]表示i变为1的方法数。初始化dp [ 1 ] \left[1\right] [1]=1.
状态转移方程: d p [ i ] = d p [ i ? x ] + d p [ i / x ] dp\left[i\right]=dp\left[i-x\right]+dp\left[i/x\right] dp[i]=dp[i?x]+dp[i/x],枚举x直接暴力,时间复杂度肯定不够
d p [ i ? x ] dp\left[i-x\right] dp[i?x]的和这个式子可以用前缀和表示
∑ x = 2 i d p [ i / x ] = d p [ i / 2 ] + d p [ i / 3 ] + d p [ i / 4 ] + … … + d p [ i / i ] \sum_{x=2}^i{dp\left[i/x\right]}=dp\left[i/2\right]+dp\left[i/3\right]+dp\left[i/4\right]+……+dp\left[i/i\right] x=2i?dp[i/x]=dp[i/2]+dp[i/3]+dp[i/4]++dp[i/i]

d p [ i / 2 ] + d p [ i / 3 ] + d p [ i / 4 ] + … … + d p [ i / i ] = d p [ i / 1 ] + d p [ i / 2 ] + d p [ i / 3 ] + d p [ i / 4 ] + … … + d p [ i / i ] ? d p [ i / 1 ] dp\left[i/2\right]+dp\left[i/3\right]+dp\left[i/4\right]+……+dp\left[i/i\right]=dp\left[i/1\right]+dp\left[i/2\right]+dp\left[i/3\right]+dp\left[i/4\right]+……+dp\left[i/i\right]-dp\left[i/1\right] dp[i/2]+dp[i/3]+dp[i/4]++dp[i/i]=dp[i/1]+dp[i/2]+dp[i/3]+dp[i/4]++dp[i/i]?dp[i/1]
这个式子可以用整除分块来做。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 200005
ll n, mod;
ll dp[MAXN];//表示i到1有几种方法
ll sum[MAXN];//dp数组的前缀和
//dp[i]=dp[i-1]+dp[i/2]
//可以减去x,可以除以x
int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> n >> mod;
	dp[1] = 1;
	sum[1] = dp[1];
	for (int i = 2; i <= n; i++)
	{
		dp[i] = (dp[i] + sum[i - 1]) % mod;
		//dp[i/2]+dp[i/3]+...+dp[i/i]=dp[i/1]+dp[i/2]+dp[i/3]+...+dp[i/i]-dp[i/1]
		ll substract = dp[i];
		ll ans = 0;
		for (int l = 1, r; l <= i; l = r + 1)//整除分块
		{
			r = i / (i / l);
			ans += ((r - l + 1) * (dp[(i / l)%mod])%mod);
		}
		dp[i] =(dp[i]+ ans - substract)%mod;
		sum[i] = (sum[i - 1] + dp[i]) % mod;
	}
	cout << dp[n];
	return 0;
}

D2普通的整除分块也不行,得把 O ( s q r t n ) O(sqrtn) O(sqrtn)的复杂度降到 O ( l o g n ) O(logn) O(logn),不会。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 07:48:45  更:2021-09-19 07:49:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:49:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码