0.题目大意

给定三个正整数m,n,k(2≤m≤1e7,1≤k≤n≤5e7)。已知一个长度为n的序列a满足(mod为题目给出的常数,为1e9+7),求a中第k小的数字。

(注意,本序列从开始,即

1.分析题目

①初步分析

首先,开一个大小为5e7的整形数组再排序是不现实的。题目的内存上限是313072KB,而一个大小为5e7的整形数组所占用的内存为195312.5KB。显然,MLE了。

同时,n的上限是5e7,而时限为1.5s。这说明什么?这说明只能用O(n)的算法通过。甚至连常数打了都不行。虽然题目的标签有一个基数排序,但是实际上这道题不能直接使用基排。(你想想,不仅不能使用数组存储数字;而且基排的常数是比较大的,不能保证卡过时限)

②打开思路

那能怎么办?如果你的思路是比较开阔的,你应该想到一道类似的题目:给出一个数组,求第k小的数字。那题数据很小,所以使用各种方法都能过。而其中最正统的写法就是运用了快排的思想:

每次选择一个“哨兵”,大于它的数字排在它左边,小于它的数字在它的右边。计算两边的元素个数,可以缩小第k小数字的范围。

但是,这个算法有一个缺点:其最优的时间复杂度为O(n),可是但凡你的运气差一点,就很可能导致两边的数字个数相差甚远。比如,你运气奇差或者题目数据有些变态,导致你每次选中的哨兵都是当前序列中的最大或最小值,那么该算法就会退化至。这是不能接受的。

所以,我们要使用另一种思路:因为这些数字的值域都很小,所以我们大可以使用一个bool数组来记录数字i是否在序列中出现过。再求一个前缀和,这题目就能轻松搞定了。

        这个思路是可以借鉴的。但是在本题中, 的理论最大值为mod-1,即1e9+6。这个数字还是太大了——5e7的数组都存不下,更何况1e9呢!思路进入了死胡同。

但是,这个“死胡同”中,并非无路可走:既然1e9的数组存不下,那我就把数字分为两部分——低五位(即个位、十位、百位、千位、万位)与高五位(十万、百万、千万、亿、十亿)。只要我们能求出第k小数字的高五位与低五位,问题就能得到解决。因为高五位的权值更大,所以我们先处理高五位,求出第k小的数字的高五位是多少。再求低五位,就能轻松搞定了

2.最终代码

①Q:但是,我们怎么求每个数字的高五位与低五位呢?

A:(精华在于注释,下同)

const int mod = 1e9 + 7, num = 1e5;
int m, n, k;
int cnt[num + 1];
cin>>m>>n>>k;
int last = 1, x, h; //h是前面5位
cnt[last/num+1]++;
for (int i = 2; i <= n; i++) {long long now=1ll*x*lastnow%=mod;x=now;cnt[x / num + 1]++; //注意,这里有一个加一,为了方便cnt[0]的处理last = x;
}

②Q:我们怎么存储个数呢?

A:

int cnt[num + 10];//cnt[i]表示值为i的个数出现的次数

③Q:我们怎么确定第k小数字的前五位呢?

A:

for (int i = 1; i <= num; i++) {cnt[i] += cnt[i - 1];if (cnt[i] >= k) {h = i - 1;//h表示第k小数字的高五位。-1是因为处理cnt[0]时会数组越界,就整体都加1k -= cnt[i - 1];//这一步不能忘。因为第一轮筛选过后k对于高五位为i的数字内部来说k应该减去cnt[i-1]break;}
}

④ Q:我悟了……

A:悟了就好,自己写完之后来核对一下代码或者自己直接交。

​
#include<iostream>//有缘千里来相见,万年不变头文件
#include<stdio.h>
#define int long long//十年OI一场空,不开long long见祖宗
using namespace std;
const int mod = 1e9 + 7, num = 1e5;//酒逢知己千杯少,定义常量莫忘了
int m, n, k;
int cnt[num + 1];
signed main() {scanf("%lld%lld%lld",&m,&n,&k);int last = 1, x, h;cnt[last/num+1]++;for (int i = 2; i <= n; i++) {x = last * m % mod;//这里开了long long,就不用担心爆int了cnt[x / num + 1]++; last = x;}for (int i = 1; i <= num; i++) {cnt[i] += cnt[i - 1];if (cnt[i] >= k) {h = i - 1;k -= cnt[i - 1];break;}}
//  printf("h:%lld k:%lld\n",h,k);for (int i = 0; i <= num; i++) {cnt[i] = 0;}last = 1;if(last/num==h) cnt[last%num+1]++;for (int i = 2; i <= n; i++) {x = last * m % mod;if(x/num==h)cnt[x%num+1]++;last = x;}for(int i=1;i<=num;i++){cnt[i]+=cnt[i-1];if(cnt[i]>=k){int answer=h*num+i-1;printf("%lld",answer);return 0;}}
}​

完结撒花!

51Nod3236-第k小生成数相关推荐

  1. 次小生成树(Prim + Kruaskal)

    问题引入: 我们先来回想一下生成树是如何定义的,生成树就是用n - 1条边将图中的所有n个顶点都连通为一个连通分量,这样的边连成子树称为生成树. 最小生成树很明显就是生成树中权值最小的生成树,那么我们 ...

  2. ACM题目————次小生成树

    Description 最小生成树大家都已经很了解,次小生成树就是图中构成的树的权值和第二小的树,此值也可能等于最小生成树的权值和,你的任务就是设计一个算法计算图的最小生成树. Input 存在多组数 ...

  3. 【数据结构与算法】【算法思想】贪心算法

    贪心算法 回溯算法 分治算法 动态规划 四种基本的算法思想:贪心算法,分治算法,回溯算法,动态规划,他们不是具体算法,常用来指导我们设计具体的算法和编码等. 一:贪心算法有很多经典应用 霍夫曼编码(H ...

  4. 现代图论笔记(二)树与二分图

    写在前面 这次介绍一些树和二分图的定义和主要性质, 以及这两种结构中常用的算法, 包括二分图的判定, 最小生成树的寻找等. 好久才更新, 只能说自己的代码能力还有欠缺, 一些算法知道思路但就是写不出来 ...

  5. 最小生成树prim、

    过年那几天确实没好好学习.在老家闲着也是闲着.可是就是没看书. 回来这几天又一直在弄个人博客.买域名云服务器备案什么的- -. 麻烦死了呢. 在腾讯花1块钱备案了一个网站www.goodgoodstu ...

  6. MangataのACM模板

    文章目录 数据结构 并查集 树状数组 二维单点修改,区间查询 二维区间修改,单点查询 二维区间修改,区间查询 线段树 单点修改,区间查询 区间更新.区间查询 主席树(区间第k小数模板) 单调栈 单调队 ...

  7. The 2021 ICPC Asia Regionals Online Contest (I)

    The 2021 ICPC Asia Regionals Online Contest (I) 写了一晚上,日- 文章目录 一. A Busiest Computing Nodes 二.D Edge ...

  8. [树上倍增][最小生成树]JZOJ P4313——电话线铺设

    Description Input Output Sample Input 6 9 4 6 3 4 2 5 6 5 4 6 1 3 5 3 5 9 5 6 8 4 1 5 4 6 4 6 2 7 2 ...

  9. 两种构造最小生成树的算法(普里姆算法,克鲁斯卡尔算法)

    (一)普里姆算法 普里姆算法求最小生成树:从生成树中只有一个顶点开始,到定点全部进入生成数为止: 2.克鲁斯卡尔算法. 思想:将所有边按其权值从小到大排一遍,从小到大依次选取边,加入最小生成树中,若加 ...

最新文章

  1. sscanf操作字符串和整型的区别
  2. java字符串转化为数组_Go 语言字符串和数组转化 | 臭大佬
  3. 使用 CORBA 和 Java IDL
  4. java oca_OCA第2部分中的Java难题
  5. 有关java的名句_关于志气的名言名句(精选50句)
  6. django-单表的增删改查-用户部门表
  7. VS2005常用插件
  8. 前端中台化,把格局做大:Node.js与测试服务探索
  9. 关于arcview 3.2 中输出图形添加坐标网格(Graticules and Measured Grids)时直接退出的问题...
  10. HTML+CSS个人简历练习
  11. 室内设计数据手册pdf_室内设计资料集pdf下载-室内设计资料集电子版pdf高清扫描版-东坡下载...
  12. LidarSLAM(一):NDT
  13. python图片转手绘_python图片转素描软件
  14. 学习笔记 -《量子计算与编程入门》- 量子程序
  15. 硬盘突然变raw格式_硬盘变成RAW格式怎么办
  16. USACO oct. 09 Watering Hole
  17. 超详细 | 贝叶斯网络基础——有图有真相
  18. swapidc的php语言,SWAPIDC目录说明及文件说明及某些常量内容
  19. 软件需求分析方法收集
  20. c语言金字塔输出乘法表,python中打印金字塔和九九乘法表的几种方法

热门文章

  1. 商业智能软件对比评测:FineBI和Tableau
  2. vue form表单数据提交与 router 按钮快速调用页面
  3. 诺基亚的最后机会:没落贵族能否抗衡苹果安卓
  4. 《痛点:挖掘小数据满足用户需求》
  5. 微信支付的软件架构也太特么牛逼了吧...
  6. 1字节不是一定是8位。
  7. 技术知识库——C1见习能力认证(应用软件开发的基础知识)
  8. 阿里云配置密钥SSH登录
  9. python 身份证识别器_基于Python的身份证验证识别和数据处理
  10. PTA乙级 1108 String复读机——20分