集合删数 (vijos 1545) 题解

【问题描述】

一个集合有如下元素:1是集合元素;若P是集合的元素,则2 * P +1,4*P+5也是集合的元素,取出此集合中最小的K个元素,按从小到大的顺序组合成一个多位数,现要求从中删除M个数位上的数字,使得剩下的数字最大,编程输出删除前和删除后的多位数字。

注:不存在所有数被删除的情况。

【样例输入】

5 4

【样例输出】

137915

95

【解题思路】

首先,我们可以将该问题转化为两个子问题:

1:求2*p+1与4*p+5两个集合中前k个数组成的数。

2:求如何删去m个数字使留下的数最大,并输出该数。

对于子问题1,其实是很好办的,直接将两个集合转化为两个队列,取走两个队列中更小的队首元素,并将其扩展放入到两个集合中,直到取出了k个数。

那么关键在于如何解决子问题2。

既然要使留下的数最大,那么自然是越高位越大越好,于是,对于某一个数字是取还是舍,我们应遵循下面两个原则:

1:如果该数字比其之前的数字大,那么我们应尽量舍去之前的数字。

2:如果舍去的数字已经有m个了,那就不必舍去了。

因此,对于每一个数字,我们应把它与它前面的数字进行比较,如果满足上述两个原则,那么就取代其之前的数。详见代码。

【代码实现】

var t,k:array[1..200000] of longint;
    sta:array[0..200000] of char;
    t1,t2,i,n,m,l,top,r1,r2:longint;
    s,st:ansistring;
begin
 readln(n,m);
 i:=1;
 t[1]:=3;
 k[1]:=9;
 t1:=1;
 t2:=1;
 r1:=1;
 r2:=1;
 s:=‘1‘;
 while i<n do
  if t[r1]<k[r2] then
   begin
    inc(i);
    str(t[r1],st);
    s:=s+st;
    inc(t1);
    t[t1]:=2*t[r1]+1;
    inc(t2);
    k[t2]:=4*t[r1]+5;
    inc(r1);
   end
  else
   begin
    inc(i);
    str(k[r2],st);
    s:=s+st;
    inc(t1);
    t[t1]:=2*k[r2]+1;
    inc(t2);
    k[t2]:=4*k[r2]+5;
    inc(r2);
   end;
 writeln(s);//解决子问题1
 l:=length(s);
 m:=l-m;
 sta[0]:=chr(57);
 top:=1;
 for i:=1 to l do
  begin
   while(s[i]>sta[top-1])and(top+l-i>m)do//满足两个原则,取代
    dec(top);
   sta[top]:=s[i];
   inc(top);
  end;
 for i:=1 to top-1 do
  if sta[i]<>‘0‘ then
   break;//注意:前导0不要输出
 for i:=i to m do
  write(sta[i]);
 writeln;
end.
时间: 2024-12-23 06:17:30

集合删数 (vijos 1545) 题解的相关文章

[Swust OJ 403]--集合删数

题目链接:http://acm.swust.edu.cn/problem/403/ Time limit(ms): 5000 Memory limit(kb): 65535 Description 一个集合有如下元素:1是集合元素:若P是集合的元素,则2 * P +1,4*P+5也是集合的元素,取出此集合中最小的K个元素,按从小到大的顺序组合成一个多位数,现要求从中删除M个数位上的数字,使得剩下的数字最大,编程输出删除前和删除后的多位数字. 注:不存在所有数被删除的情况 Input 输入的仅一行

[来源不详]删数方案数

Description 给出一个正整数序列 a,长度为 n,cyb 不喜欢完美,他要删掉一些数(也可以不删,即删掉0个),但是他不会乱删,他希望删去以后,能将 a 分成 2 个集合,使得两个非空集合的数的和相同,现在他希望你能帮他算出删数的方案数. Input 第一行 n 个正整数 以下有 n行,每行1个 正整数表示整数序列a Output 一个整数表示答案 Sample Input 4 1 2 3 4 Sample Output 3 Hint 30%:n<=5 100%:n<=20 100%

删数方案数(regex)

[题目描述] 给出一个正整数序列 a,长度为 n,cyb 不喜欢完美,他要删掉一些数(也可以不删,即删掉0个),但是他不会乱删,他希望删去以后,能将 a 分成 2 个集合,使得两个非空集合的数的和相同,现在他希望你能帮他算出删数的方案数. [输入文件] 第一行 n 个正整数 以下有 n行,每行1个 正整数表示整数序列a [输出文件] 一个整数表示答案 [输入样例] 4 1 2 3 4 [输出样例] 3 [数据范围] 30%:n<=5 100%:n<=20 100%:a 中每个元素<=10

4906 删数问题

4906 删数问题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 键盘输入一个高精度的正整数N,去掉其中任意S个数字后剩下的数字按原左右次序将组成一个新的正整数.编程对给定的N 和S,寻找一种方案使得剩下的数字组成的新数最小. 输入数据均不需要判错. 输出组成的新的正整数.(N不超过240位) 输入描述 Input Description 第一行,输入一正整数N(N<=10240),表示要删的数: 第二行,

dtoi4375「BJOI2019」删数

题意: 对于任意一个数列,如果能在有限次进行下列删数操作后将其删为空数列,则称这个数列可以删空.一次删数操作定义如下: 记当前数列长度为 k,则删掉数列中所有等于 k 的数. 现有一个长度为 n 的数列 a,有 m 次修改操作,第 i 次修改后你要回答:经过 i 次修改后的数列 a,至少还需要修改几个数才可删空? 每次修改操作为单点修改或数列整体加一或数列整体减一. 题解:      如果一个我要删去大小为a的数,那么序列长度会变成a-h[a](h[a]为数值a出线的次数).那么我们意会一下这个

codevs4096 删数问题

题目描述 Description 键盘输入一个高精度的正整数N,去掉其中任意S个数字后剩下的数字按原左右次序将组成一个新的正整数.编程对给定的N 和S,寻找一种方案使得剩下的数字组成的新数最小. 输入数据均不需要判错. 输出组成的新的正整数.(N不超过240位) 输入描述 Input Description 第一行,输入一正整数N(N<=10240),表示要删的数: 第二行,输入一正整数S,表示删去的个数,当然S小于N的位数. 输出描述 Output Description 仅一行,输出删数后形

洛谷P1106 删数问题

题目描述 键盘输入一个高精度的正整数N,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数.编程对给定的N和k,寻找一种方案使得剩下的数字组成的新数最小. 输出应包括所去掉的数字的位置和组成的新的整数.(N不超过250位) 输入数据均不需判错. 输入输出格式 输入格式: n (高精度的正整数) k (需要删除的数字个数) 输出格式: 最后剩下的最小数. 输入输出样例 输入样例#1: 175438 4 输出样例#1: 13分析:贪心思想,我们每次删数肯定是要找前面的大数给删掉,并且这

1106 删数问题

1106 删数问题 难度:普及/提高- 题目类型:贪心 提交次数:3 涉及知识:字符串.贪心 题目描述 键盘输入一个高精度的正整数N,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数.编程对给定的N和k,寻找一种方案使得剩下的数字组成的新数最小. 输出应包括所去掉的数字的位置和组成的新的正整数.(N不超过250位) 输入数据均不需判错. 代码: #include<iostream> #include<cstring> using namespace std; int

bzoj2734【HNOI2012】集合选数

2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 831  Solved: 487 [Submit][Status][Discuss] Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中.同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数