HGOI 20190711 题解
Problem A 矩阵第K小数
给定一个$n \times m$的矩阵,位置$A_{i,j} = i\times j$,
给出$Q$个询问,每一次查询矩阵中第$Q_i$小的数是多少。
对于100%的数据 , $1 \leq n,m \leq 10^9 , Q \leq 100 , 1 \leq Q_i \leq n\times m$
Sol : 本题采用暴力模拟的复杂度是不能通过的,并且其矩阵的排布都是有规律的。
第$i$行构成的数列是公差为$i$的等差数列。 可以考虑枚举每一行,然后就可以O(1) 计算这一行有多少比某一数$x$小了。
同时,对于每一个询问二分答案,然后可以扫一遍$n$然后二分计算每一行的贡献。这样的复杂度就是$O(Qnlog_{2} (nm) )$
同时考虑,每一行贡献是类似于$\lfloor \frac{x}{i} \rfloor$的东西,我们会发现这个东西对于$i$递增,它可能的取值只会有$\sqrt{x}$种。
并且其值是单调下降的。 所以我们可以$O(\sqrt{n})$每次遍历每一个"平台"。但是由于需要二分答案,这样的复杂度会变成$log_2 n \sqrt{n}$
总时间复杂度会变成$O(Q\sqrt{n} log_{2} (nm) log_2 n)$无法通过。
如何在$O(\sqrt{n})$的复杂度遍历每一个块,然后统一计算是本题的瓶颈。
问题等价于求$\sum\limits_{i=1}^n \lfloor \frac{x}{i} \rfloor $,我们可以考虑一个$i$满足$a = \lfloor \frac{x}{i} \rfloor $
在某一个区间内,有$a \leq \lfloor \frac{x}{i} \rfloor < a+1 $ ,所以可以解得此时的$i \in [\left \lfloor \frac{x}{\left \lfloor \frac{x}{i} \right \rfloor+1} \right \rfloor + 1, \left \lfloor \frac{x}{\left \lfloor \frac{x}{i} \right \rfloor} \right \rfloor]$
所以最后的复杂度就可以做到$O(Qlog_2 (nm) \sqrt{n} )$ 了。
# pragma GCC optimize(3) # include <bits/stdc++.h> # define int long long using namespace std; int n,m,q; inline int read() {int X=0,w=0; char c=0;while(c<'0'||c>'9') {w|=c=='-';c=getchar();}while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();return w?-X:X; } int calc(int i,int x){if (x%i==0) return min(x/i-1,m);else return min(x/i,m); } bool check(int x,int k) {int ret=0;for (int l=1,r;l<=min(x,m);l=r+1) {r=x/(x/l);ret+=min((x/l),n)*(r-l+1);} return (ret>=k); } signed main() {n=read();m=read();q=read();while (q--) {int x=read(); int l=1,r=n,ans;while (l<=r) {int mid=(l+r)>>1;if (check(mid,x)) ans=mid,r=mid-1;else l=mid+1;}printf("%lld\n",ans);}return 0; }
mat.cpp
Problem B 最小极差生成树
给出$n$个点$m$条边的连通图$G=(V,E)$,求出一棵生成树使得其最大边权和最小边权的差最小。
对于100%的数据$1 \leq m\leq 4000 , 1 \leq n \leq 1000$
Sol : 枚举每一条边,以这条边权$s$为下界跑最小生成树,找出最小生成树的最大边权为$d$.
用$d-s$更新答案。注意可能会有不合法情况,输出-1即可。
# pragma GCC optimize(3) # include <bits/stdc++.h> using namespace std; const int N=4e3+10; int n,m,f[N]; struct node{ int u,v,w;}E[N]; bool cmp(node a,node b) {return a.w<b.w;} inline int read() {int X=0,w=0; char c=0;while(c<'0'||c>'9') {w|=c=='-';c=getchar();}while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();return w?-X:X; } int father(int x) {if (f[x]==x) return x;return f[x]=father(f[x]); } int MST(int W) {for (int i=1;i<=n;i++) f[i]=i;int tmp=0,o=0;for (int i=1;i<=m;i++) {if (E[i].w<W) continue;int fx=father(E[i].u),fy=father(E[i].v);if (fx==fy) continue;tmp++; f[fx]=fy; o=max(o,E[i].w);if (tmp==n-1) break;}if (tmp!=n-1) return -1;else return o; } int main() {int T=read();while (T--) {n=read();m=read();for (int i=1;i<=m;i++) {int u=read(),v=read(),w=read(); E[i]=(node){u,v,w};}sort(E+1,E+1+m,cmp);int ans=-1;for (int i=1;i<=m;i++) {int t=MST(E[i].w);if (t==-1) continue;if (ans==-1) ans=t-E[i].w;else ans=min(ans,t-E[i].w);}printf("%d\n",ans);}return 0; }
min.cpp
Problem C 数字分组
个体互异而值可能相同$n$个数$a_i$划分为若干组。 对于某一组记下这组元素的极差(最大数-最小数)
一种合法的划分要求每一组元素极差的和有$\leq M$的限制。求出所有合法划分的总数$mod \ 10^9 + 7$的值。
对于20%的数据 ,$1 \leq n \leq 10$ ; 对于另外20%的数据,$M=0$
对于100%的数据,$1 \leq n \leq 200,0 \leq M \leq 1000,1 \leq a_i \leq 500 $
Sol : 对于20%数据直接第二类斯特林数求和然后乘起来即可。
对于100%的数据考虑DP。
先对数据排序,记$f_{i,j,k}$表示前$i$个数,还有$j$个划分集可以添加元素,当前差值和为$k$方案总数。
首先,显然即将添加的数$a_i$一定比之前添加的所有数要大,所以对于每一个没有完全划分好的集合都有贡献。首先计算当前差值的和是多少,我们会向每一个没有划分好的集合中添加一个差值$a_i - a_{i-1}$ , 所以当前差值的和就是$k + (a_i - a_{i-1})\times j$.
这是因为每一组的最值差就是这一组当中最大值和最小值之间所有数的差的和 。
所以这$j$组由于没有被划分好,就需要向里面添加这个差值$a_i - a_{i-1}$
考虑新添加这个元素作为一个新的分组的开始:$f_{i,j+1,v} += f_{i-1,j,k}$
考虑新添加的这个元素作为一个新的分组的开始和结束:$f_{i,j,v} += f_{i-1,j,k}$
考虑新添加的元素作为之前一个旧的还没划分好的组的非结束的元素:$f_{i,j,v} += f_{i-1,j,k}\times j$ ($j \neq 0 $)
考虑新添加的元素作为之前一个旧的还没划分好的组的结束元素$f_{i,j-1,v} += f_{i-1,j,k}\times j$ ($j \neq 0 $)
注意到这里枚举的状态$k$表示的是由那一维状态转移过来的状态$k$
用滚动数组实现就可以排除空间限制。
复杂度$O(n^2k)$
# pragma GCC optimize(3) # include <bits/stdc++.h> # define int long long using namespace std; const int mo=1e9+7; int f[2][205][1005]; int a[205]; int n,w; signed main() {scanf("%lld%lld",&n,&w);for (int i=1;i<=n;i++) scanf("%lld",&a[i]);sort(a+1,a+1+n);int p=0; f[p][0][0]=1; for (int i=1;i<=n;i++) {p^=1; memset(f[p],0,sizeof(f[p]));for (int j=0;j<=i;j++)for (int k=0;k<=w;k++) {int v=(a[i]-a[i-1])*j+k;if (v>w) continue;f[p][j+1][v]+=f[p^1][j][k]; f[p][j+1][v]%=mo;f[p][j][v]+=f[p^1][j][k];f[p][j][v]%=mo;if (j) {f[p][j][v]+=f[p^1][j][k]*j; f[p][j][v]%=mo;f[p][j-1][v]+=f[p^1][j][k]*j;f[p][j-1][v]%=mo;} } }int ret=0;for (int k=0;k<=w;k++)ret+=f[p][0][k],ret%=mo;printf("%lld\n",ret); return 0; }
grp.cpp
转载于:https://www.cnblogs.com/ljc20020730/p/11170096.html
HGOI 20190711 题解相关推荐
- HGOI 20190709 题解
Problem A 紫色激情 一个序列$\{a_n\}$,求出方差最大的子序列. 其中方差 [l,r] 的定义是$S^2 = \frac{1}{n} \sum\limits_{i=l}^{r} (x_ ...
- HGOI 20181103 题解
problem:把一个可重集分成两个互异的不为空集合,两个集合里面的数相乘的gcd为1(将集合中所有元素的质因数没有交集) solution:显然本题并不是那么容易啊!考场上想了好久.. 其实转化为上 ...
- [JS][dfs]题解 | #迷宫问题#
题解 | #迷宫问题# 题目链接 迷宫问题 题目描述 定义一个二维数组 N*M ,如 5 × 5 数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 1, 1 ...
- [JS][dp]题解 | #打家劫舍(一)#
题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...
- [JS]题解 | #魔法数字#
题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...
- [JS]题解 | #岛屿数量#
题解 | #岛屿数量# 题目链接 岛屿数量 题目描述 时间限制:1秒 空间限制:256M 描述 给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右 ...
- [JS] 题解:提取不重复的整数
题解:提取不重复的整数 https://www.nowcoder.com/practice/253986e66d114d378ae8de2e6c4577c1 时间限制:1秒 空间限制:32M 描述 输 ...
- 洛谷-题解 P2672 【推销员】
独门思路!链表加优先队列! 这题一望,贪心是跑不掉了,但是我贪心并不好,所以想到了一个复杂一些但思路更保稳的做法 思路: 1 因为是离线操作,所以我们可以倒着求,先求x=n的情况,因为那样直接就知道了 ...
- [洛谷1383]高级打字机 题解
题解 这道题一看就珂以用主席树啊 这是一道神奇的题目,那么我们先敲一个主席树,然后维护一个数组len,表示下一次应该在len + 1插入, 之后对于T操作,在上一个版本的len + 1上直接执行插入 ...
最新文章
- Replication的犄角旮旯(五)--关于复制identity列
- Spring Boot定时任务-cron表达式
- JS判断访问设备(userAgent)加载不同页面 JS判断客户端操作系统类型(platform)
- 分享我们承建的三篇NAR的数据库
- 音频断句Matlab,一步一步教你实现iOS音频频谱动画(二)
- 持续集成和持续部署CI/CD简介
- 在ASP.NET应用启动的时候初始化的几种方法
- 在Vue+springBoot环境中如何实现单点登录(SSO)
- 天啊!才几天没去看新闻,WinCE就有这么“爆炸”的新闻了?
- Google / Baidu 黑客搜索引擎语法详细记录
- 11的倍数c语言,11-1,5,11,12的倍数(容斥原理)
- Word 2016使用技巧
- php计算排名,成绩相同需要并列算法
- 使用Github和PicGO搭建免费图床
- 一米村长讲故事机器人_又一位主持人跑去给孩子讲故事,村长李锐推出有声故事品牌“村长讲故事”...
- 全球程序员收入出炉!北京收入排入全球第十
- BinaryWriter
- 〖Python 数据库开发实战 - MySQL篇⑥〗- 利用 PyCharm 链接 MySQL 实现数据库可视化
- 开放平台支持的签名算法
- 【LeetCode算法 - JAVA】6.Z字形变换
热门文章
- hex文件格式学习记录
- 大数据分析师面试求职攻略
- 【Android】java.lang.SecurityException: getDeviceId: Neither user xxxxx nor current process has andro
- 177本名著浓缩成了177句话!
- Lua环境搭建 Win10
- Java基础之MySQL(二)
- 背锅侠?程序出现bug是测试/开发工程师水平有限导致的?我只是个搬砖的......
- UESTC 1144 Big Brother
- ETHPLANET 黑客松报名最后10天!来领福利喽~
- 一个23届蔡鸡渣硕找实习的经历(附部分记录了还想得起来的面经)