当前位置: 首页 > news >正文

012组合数学——算法备赛

顺序五元组

给定一个整数数组A(长度N大于等于5),请问有多少个五元组(a,b,c,d,e)满足以下条件

  • 0<a<b<c<d<e<N
  • Aa+Ab=Ac=Ad+Ae

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll sol(unordered_map<int, int>& m, int x) {ll res = 0;for (auto& [v, c] : m) {if (v * 2 == x)res += (c * (c - 1));  //每个v都多算一次,所以最后除以2else if (m.count(x-v))res += c * m[x - v];  //当遍历到x-v时又计算一次,所以最后除以2}return (res >> 1ll);
}
int main() {int N;cin >> N;vector<int> A(N);unordered_map<int, int> m1, m2;for (int i = 0; i < N; i++) {cin >> A[i];m2[A[i]]++;  //统计后部分即[c+1,N-1]部分元素频数}ll ans = 0;for (int i = 0; i < N - 2; i++) {m2[A[i]]--;if (i > 1) ans += sol(m1, A[i]) * sol(m2, A[i]);m1[A[i]]++;}cout << ans << endl;return 0;
}

监控竞赛

问题描述

大赛共有N位参赛者,第i位参赛者编号为i,来自编号为Ai的国家。比赛机房的电脑从左到右依次编号1~N,每位参赛者在与自己编号相同的电脑上进行比赛。官方决定对部分参赛者的电脑进行监控。监控方式满足以下条件:

  1. 监控的电脑数量不为0
  2. 同一国家的参数者最多只能有两台电脑被监控
  3. 如果同一国家的两台电脑被监控,它们的距离不能超过d。这里的距离表示两台电脑的编号差值的绝对值。

请求出所有满足条件的监控方案数,结果对10^9+7取余。

原题链接

思路分析

每个国家选取队员相互独立,可以使用乘法原理,计算出每个国家选取队员的方案数,最后总方案数为所有国家选取队员的方案数的乘积,最后去除全0的特殊方案数就是答案。

对于计算每个国家选取队员的方案数,选0或1个的方案数就是1+n(n为队员数量),选两个时要考虑队员编号距离,可以用二分法快速求解。

代码

#include<bits/stdc++.h>
using namespace std;
const int M = 1e9+7;int main() {int n,d,x;cin>>n>>d;unordered_map<int, vector<int>> mp;for (int i=1; i<=n; i++)cin>>x, mp[x].push_back(i);long long ans = 1;for (auto &[k, vec]: mp) {long long tmp = 1+vec.size();  //初始取0个或1个的方案数for (int i=0; i<vec.size(); i++)  //固定选取vec[i]为较小值,求较大值的个数tmp += (upper_bound(vec.begin(), vec.end(), vec[i]+d) - vec.begin()) - i - 1;  //减1去除选自己的情况ans *= tmp%M;  ans %= M;}cout<<ans-1;  //去除全0的特殊方案return 0;
}

公司命名

问题描述

给你一个字符串数组 ideas 表示在公司命名过程中使用的名字列表。公司命名流程如下:

  1. ideas 中选择 2 个 不同 名字,称为 ideaAideaB
  2. 交换 ideaAideaB 的首字母。
  3. 如果得到的两个新名字 不在 ideas 中,那么 ideaA ideaB串联 ideaAideaB ,中间用一个空格分隔)是一个有效的公司名字。
  4. 否则,不是一个有效的名字。

返回 不同 且有效的公司名字的数目。

原题链接

思路分析

首先建立一个大小为26的哈希集合用于按首字母分类存放后缀(除首字母剩下字符组成的字符串)

然后用两个指针a,b从左往右遍历哈希数组(分别指向一个字母,代表两个参与公司命名的两个集合)

在枚举a集合中的元素ai,看b集合是否存在,若b集合存在遍历到的该元素bi,表明ai与b中的任意元素交换首字母后存在于原数组ideas中,bi与a中任意元素交换首字母后存在于原数组ideas中,所以a,b集合中的这两个对应字符串不参与乘法原理组合

示例:

在这里插入图片描述

用m统计不参与乘法原理组合的字符串对数(两集合交集后缀对数),剩下的元素按乘法原理组合所得的结果就是从当前两个集合选取两个字符串组成合法有效公司名字的组合数

接续选取两个集合,统计一共有ans合法有效的字符串组合数,2*ans(乘2是因为两字符串可以调换顺序)就是总的不同 且有效的公司名字的数目。

long long distinctNames(vector<string>& ideas) {unordered_set<string> groups[26];for (auto& s : ideas) {groups[s[0] - 'a'].insert(s.substr(1)); // 按照首字母分组}long long ans = 0;for (int a = 1; a < 26; a++) { // 枚举所有组对for (int b = 0; b < a; b++) {int m = 0; // 交集的大小for (auto& s : groups[a]) {m += groups[b].count(s);}ans += (long long) (groups[a].size() - m) * (groups[b].size() - m);}}return ans * 2; // 乘 2 放到最后}

时间复杂度:O(nm∣Σ∣),其中 nideas 的长度,m≤10 为单个字符串的长度,∣Σ∣=26 是字符集合的大小。

总结

本题关键是将普通的数组转换为按前缀分组的哈希集合数组,再在哈希集合数组上遍历,比暴力法直接在原数组上做两重循环(复杂度O(n^2*m)要优。某些场景下预处理原始数据对解决问题很有必要。

只含3种数字的n位数

问题描述

给定一个整数n,求恰好包含3种数字(0~9中的3种数字)的n位数有多少个?该n位数不含前导0,结果对1e9+7取余

输入:第一行输入t(1<=t<=1e5),表示有t个测试用例

​ 接下来t行,每行输入一个n(1<=n<=1e5),表示数值位数

输出:对于每个测试用例,输出一个整数代表答案

代码

#include <iostream>
using namespace std;
/*
dp[i][j] i 位数 j+1 种不同的数字
*/long long dp[100001][3];
int mid = 1e9 + 7;
int main()
{int t;cin >> t;dp[3][2] = 9*9*8; dp[3][1] = 9 * 9 * 2 + 9 * 9;//排列组合for (int i = 4; i <= 100000; i++){dp[i][1] = (dp[i - 1][1] * 2 + 9 * 9) % mid;dp[i][2] = (dp[i - 1][1] * 8 + dp[i - 1][2] * 3) % mid;}while (t--) {int x;cin >> x;if (x < 3) cout << 0 << endl;else cout << dp[x][2] << endl;}return 0;
}

必胜区间

N位师傅依次落座,第i位师傅的资历值为Ai。从左往右,师傅的资历值逐级递增。同时,每位师傅带来了自己精心制作的产品,其第i位师傅的产品的评分依次为Bi。

选择一个区间[L,R],让这个区间的师傅们两两比拼

  • 如果师傅i的产品评分小于师傅j的产品评分(i<j),则双方交换产品,否则不交换。
  • 双方的得分为资历值+持有产品评分,得分高者获胜,得分相同平局。

必胜区间定义:区间长度大于等于2,区间内任意两个师傅比拼,资历高的师傅都必定获胜。

请问必胜区间有多少个?

原题链接

思路分析

师傅按资历值Ai排列,若A1+max(B1,B2)<A2+min(B1,B2),A2+max(B2,B3)<A3+min(B2,B3)那么A1+max(B1,B2)<A3+min(B2,B3)

证明如下:

A1+max(B1,B2)<A2+min(B1,B2)max(B1,B2)-min(B1,B2)<A2-A1,那么B2-B1<A2-A1恒成立。

同理若A2+max(B2,B3)<A3+min(B2,B3),那么B3-B2<A3-A2恒成立

两式合并得(B3-B2)+(B2-B1)<(A3-A2)+(A2-A1)化简得B3-B1<A3-A1

  • 当B1=min(B1,B3),根据B3-B1<A3-A1A1+B3<A3+B1A1+max(B1,B2)<A3+min(B2,B3)
  • 当B3=min(B1,B3),即B3<=B1,因为A1<A3,那么A1+B3<A3+B1A1+max(B1,B2)<A3+min(B2,B3)

综上所述:如果A1+max(B1,B2)<A2+min(B1,B2),A2+max(B2,B3)<A3+min(B2,B3)那么必有A1+max(B1,B2)<A3+min(B2,B3)

根据以上结论,延伸一下,不难得出,对于i<j<k,如果Ai+max(Bi,Bj)<Aj+min(Bi,Bj),Aj+max(Bj,Bk)<Ak+min(Bj,Bk)那么必有Ai+max(Bi,Bk)<Ak+min(Bj,Bk)。说明师傅的总得分符合递推式。

如果一个区间内所有相邻的师傅都满足必胜条件,那么区间内任意连个师傅也必然满足必胜区间。两者是充分必要的关系。

那么解决此问题只需O(n)的时间复杂度,因为判断相邻师傅就行。剩下一步就是数区间了,先找到尽可能大的区间,那么它的所有长度大于等于2的子区间都必然满足条件,对于长度为x的区间,它的所有长度大于等于2的子区间个数为1+2+…+x-1,即(x*(x-1))/2

代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// #define int long long
int n, k1 = 1;
long long sum=0;
vector<int> v1, v2;
signed main()
{cin >> n;for (int i = 0, i1; i < n; i++, v1.push_back(i1))cin >> i1;for (int i = 0, i1; i < n; i++, v2.push_back(i1))cin >> i1;for (int i = 1; i < n; i++){if (v1[i] + min(v2[i - 1], v2[i]) > v1[i - 1] + max(v2[i - 1], v2[i]))k1++;elsesum += (long long)k1 * (k1 - 1) / 2, k1 = 1;}if (k1 != 1)sum += (long long)k1 * (k1 - 1) / 2;cout << sum;
}
http://www.xdnf.cn/news/163351.html

相关文章:

  • [创业之路-390]:人力资源 - 社会性生命系统的解构与重构:人的角色嬗变与组织进化论
  • 前端职业发展:如何规划前端工程师的成长路径?
  • RAG技术解析:以Text2SQL为例看检索增强生成的全流程应用
  • 第1章 基础知识
  • brew 安装openjdk查看其版本
  • 一文了解TOGAF 认证考试,如何选择科目?
  • ROS 快速入门教程05
  • 如何保证线程安全(含典型手段与应用场景)
  • Maven插件下载失败?三步解决SSL握手错误与镜像配置
  • 【蓝桥杯省赛真题56】Scratch抓不住的蜜蜂 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解
  • 72.评论日记
  • CMCC RAX3000M CH EC 算力版刷机(中国移动 RAX3000M 算力版)刷机
  • 大模型的使用
  • 2025年暨南大学 ACM校赛分析与题解
  • 二、UI自动化测试02--元素定位方法
  • 【赵渝强老师】快速上手TiDB数据库
  • 线程池(四):并发编程常见问题解析
  • java基础之枚举和注解
  • NdrpConformantVaryingArrayUnmarshall函数分析--重要
  • 【家政平台开发(79)】解锁家政新金融:家政平台与金融服务融合之道
  • 基于大模型的急性肠套叠全流程预测与诊疗方案研究报告
  • Java 变量入门指南
  • 什么是WebSocket?NGINX如何支持WebSocket协议?
  • 数据可视化大屏——大数据分析系统
  • C#进阶学习(十四)反射的概念以及关键类Type
  • 【Linux C/C++开发】使用hash算法进行性能优化
  • 【读论文】面向小目标的轻型变电设备缺陷检测算法
  • 力扣刷题Day 30:两数相加(2)
  • Simulink 数据存储机制:Base Workspace、Model Workspace 与 Data Dictionary 的核心区别
  • 2025.04.26-饿了么春招笔试题-第二题