2023牛客寒假算法基础集训营2(ABC)

(水博客预警

关于补了题才发现这三道题真的很有意思这件事

A就是一个单纯的暴力枚举

B是由于数据范围过大而不得不进行的推公式(涉及到两个区间求交集的运算技巧和公式)

C是考察对于B的理解和灵活运用程度(顺便考察了取模运用)

2023牛客寒假算法基础集训营2_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

题目是看了题解才明白的,并为这有趣的公式和思路感到震惊

对于B题,给出了两个范围,要求满足从两个范围中各取一数a, b使得a + b = n,只需判断a或b的取值范围(这里我们用a的范围为例),答案从两个范围取大值即可。

首先,a本身是a ∈ [L1, R1],又n - a = b,则n - a ∈ [L2, R2]  ==> a ∈ [n - R2, n - L2] ,显然,a的取值便是[L1, R1] ∩ [n - R2, n - L2]。

而求交集的代码公式也很好理解

x ∈ [max(L1, n - R2), min(R1, n - L2)] (后边界取小,前边界取大)

同理推出求并集公式

x ∈ [min(L1, n - R2), max(R1, n - L2)] (后边界取大,前边界取小)

(这是不是就算把数学和代码联系到一起辣!

此外还要注意如果R1和R2之和小于n和L1和L2之和大于n的情况是取不到结果的,直接就是0了(也可以if特判答案小于等于0的情况都输出0)

AB已ac代码:

#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
#define ll long long
#define int ll
using namespace std;
const int maxn = 1e6 + 10;

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie();
	cout.tie();
	int t;
	cin>>t;
	while (t--) {
		int n;
		cin>>n;
		int l1, l2, r1, r2;
		cin>>l1>>r1>>l2>>r2;
        if (l1 + l2 > n || r1 + r2 < n) {
            cout<<"0\n";
            continue;
        }
		cout<<max(min(r2, n - l1) - max(l2, n - r1) + 1, min(r1, n - l2) - max(l1, n - r2) + 1)<<"\n";
	} 
	return 0;
}

对于C题,已经给出了许多个区间的情况下,任选两个不同的区间进行前边的计算,就是用全部的可能性减去同一个区间自身取的情况,全部可能性是枚举n范围内的数字i,用他所出现过的区间个数 * (n - i) 出现过的区间个数;自身取就是B题的简化,两个范围都是L到R,套用公式舍去小于0或2 * L > n和2 * R < n的情况(一个意思);外加取模运算和减法取模的特性即可求解。

C题已ac代码:

#include<bits/stdc++.h>
#define ll long long
#define int ll
using namespace std;
const int mod = 998244353;
const int maxn = 1e6 + 10;
int box[maxn];
signed main()
{
	int n, m;
	cin>>n>>m; 
	int sum1 = 0;
	while (m--) {
		int l, r;
		cin>>l>>r;
		box[l]++;
		box[r + 1]--;
        if (2 * l > n || 2 * r < n || n - l < 0) {
            continue;
        }
//         if (min(r, n - l) - max(l, n - r) + 1 <= 0) {
//             continue;
//         }
		sum1 = sum1 % mod + (min(r, n - l) - max(l, n - r) + 1) % mod;
	}
	for (int i = 1; i <= maxn; i++) {
		box[i] = (box[i - 1] + box[i]) % mod;
	}
	int sum2 = 0;
	for (int i = 1; i < n; i++) {
		sum2 = sum2 % mod + box[i] % mod * (box[n - i] % mod) % mod;
	}
	cout<<(sum2 % mod - sum1 % mod + mod) % mod;
	return 0;
}

by yq

ps:水博客+记录公式和想题思路,扩展对于有关贡献值的题目的考虑方式

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超高校级のDreamer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值