题目链接

Problem Description

As we all known, merge sort is an O(nlogn) comparison-based sorting algorithm. The merge sort achieves its good runtime by a divide-and-conquer strategy, namely, that of halving the list being sorted: the front and back halves of the list are recursively sorted separately, then the two results are merged into the answer list. An implementation is shown as follows:

The procedure Merge(L1,L2:in List_type;L:out List_type) that we have in mind for sorting two lists is described as follows. Initialize pointers to the first item in each list L1,L2, and then

repeat

compare the two items pointed at;

move the smaller into L;

move the pointer which originally points at the smaller one to the next number;

until one of L1,L2 exhausts;

drain the remainder of the unexhausted list into L;

Now let us come to the situation when there are k pointers, here k≥2. Let L be a list of n elements. Divide L into k disjoint contiguous sublists L1,L2,…,Lk of nearly equal length. Some Li’s (namely, n reminder k of them, so possibly none) will have length  , let these have the low indices: L1,L2,…,Ln%k Other Li’s will have length , and high indices are assigned: Ln%k+1,…,Lk-1,Lk. We intend to recursively sort the Li’s and merge the k results into an answer list.

We use Linear-Search-Merge here to merge k sorted lists. We find the smallest of k items (one from each of the k sorted source lists), at a cost of k-1 comparisons. Move the smallest into the answer list and advances its corresponding pointer (the next smallest element) in the source list from which it came. Again there are k items, from among which the smallest is to be selected. (When i (1 ≤ i < k) lists are empty, k-way merging sort becomes to (k-i)-way merging sort, and the draining process will start when the total order of all the elements have been found)

Given a list containing n elements, your task is to find out the maximum number of comparisons in k-way merging sort.

 Input

The first line of the input contains an integer T (T <= 100), indicating the number of cases. Each case begins with a line containing two integer n (1 ≤ n ≤ 10100) and k (2 ≤ k ≤ 20), the number of elements in the list, and it is k-way merging sort.

 Output

For each test case, print a line containing the test case number (beginning with 1) and the maximum number of comparisons in k-way merging sort.

 Sample Input

4
2 2
3 2
100 7
1000 10

 Sample Output

Case 1: 1
Case 2: 3
Case 3: 1085
Case 4: 22005
 
 
题意:对于归并排序,本来是2-路分治,现在要求k-路分治,求n个元素下k-路分治归并排序所需要的最大比较次数?
 
思路:对于n个元素k-路分治,将元素1~n分为k段,前s=n%k段每段有n/k+1个元素,后k-s段每段有n/k个元素,那么对这k段进行归并时和2-路一样,选出这k段中的最小值放入合并后的数组,每次从k段中选出一个最小值需要比较k-1次,当每一段均剩下一个元素时,共选出了n-k个最小值,所以比较了(k-1)*(n-k)次,对于剩下的k个元素则需要比较(k-1)+(k-2)+……+1=(k-1)*k/2 次,所以共需要(k-1)*(n-k)+(k-1)*k/2次,然后递归进一步分治,注意使用记忆化搜索。
 
注意:本题数据很大所以不能用数组存值,而用的map映射的。
 
代码如下:
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner; public class Main{
static Map<BigInteger,BigInteger>dp = new HashMap<BigInteger,BigInteger>();
static BigInteger n, ans;
static int k;
static BigInteger dfs(BigInteger len, BigInteger x){
if(dp.containsKey(len)) return x.multiply(dp.get(len));
if(len.compareTo(BigInteger.valueOf(k))<=0){
return x.multiply(len.subtract(BigInteger.ONE)).multiply(len).divide(BigInteger.valueOf(2));
}
BigInteger tmp = (BigInteger.valueOf(k).subtract(BigInteger.ONE)).multiply((len.subtract(BigInteger.valueOf(k))));
tmp = tmp.add(BigInteger.valueOf(k).multiply(BigInteger.valueOf(k).subtract(BigInteger.ONE)).divide(BigInteger.valueOf(2)));
BigInteger kk = len.mod(BigInteger.valueOf(k));
if(kk!=BigInteger.ZERO){
tmp=tmp.add(dfs(len.divide(BigInteger.valueOf(k)).add(BigInteger.ONE),kk));
}
tmp = tmp.add(dfs(len.divide(BigInteger.valueOf(k)),BigInteger.valueOf(k).subtract(kk)));
dp.put(len, tmp);
return tmp.multiply(x);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int T = in.nextInt();
for(int cas=1; cas<=T; cas++){
dp.clear();
n = in.nextBigInteger();
k = in.nextInt();
ans=dfs(n, BigInteger.ONE);
System.out.println("Case "+cas+": "+ans);
}
}
}

下面这个是我先用c++写的版本,用来验证算法,上面的java是用这c++代码改写的(其实一样)。

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <map>
using namespace std;
typedef long long LL;
LL n,k;
map<LL,LL>mp; LL dfs(LL len,LL x)
{
if(mp.count(len)) return x*mp[len];
if(len<=k) return x*(len-)*len/;
LL tmp=(k-)*(len-k);
tmp+=k*(k-)/;
tmp+=dfs(len/k+(len%k!=),(len%k));
tmp+=dfs(len/k,(k-len%k));
mp[len]=tmp;
return tmp*x;
} int main()
{
while(scanf("%lld%lld",&n,&k)!=EOF)
{
mp.clear();
LL ans=dfs(n,);
cout<<"final ans = "<<ans<<endl;
}
return ;
}

FZU 1919 -- K-way Merging sort(记忆化搜索)的更多相关文章

  1. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

  2. loj 1021(状压dp+记忆化搜索)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25887 题目大意:给定的一个某进制下的排列,问它的全排列有多少个能 ...

  3. FZU 2092 bfs+记忆化搜索

    晚上团队训练赛的题 和普通bfs不同的是 这是同时操纵人与影子两个单位进行的bfs 由于可能发生人和影子同时接触水晶 所以不可以分开操作 当时使用node记录人和影子的位置 然后进行两重for循环来分 ...

  4. FZU 2092 收集水晶 bfs+记忆化搜索 or 暴力

    题目链接:收集水晶 一眼看过去,觉得是普通的bfs,初始位置有两个.仔细想了想...好像如果这样的话..........[不知道怎么说...T_T] dp[12][12][12][12][210] 中 ...

  5. FZU 2092 收集水晶(记忆化搜索)

    Problem 2092 收集水晶 Accept: 101 Submit: 439 Time Limit: 5000 mSec Memory Limit : 32768 KB Problem Desc ...

  6. E. Santa Claus and Tangerines 二分答案 + 记忆化搜索

    http://codeforces.com/contest/752/problem/E 首先有一个东西就是,如果我要检测5,那么14我们认为它能产生2个5. 14 = 7 + 7.但是按照平均分的话, ...

  7. cdoj Dividing Numbers 乱搞记忆化搜索

    //真tm是乱搞 但是(乱搞的)思想很重要 解:大概就是记忆化搜索,但是原数据范围太大,不可能记下所有的情况的答案,于是我们就在记下小范围内的答案,当dfs落入这个记忆范围后,就不进一步搜索,直接返回 ...

  8. UVA 103 Stacking Boxes (dp + DAG上的最长路径 + 记忆化搜索)

     Stacking Boxes  Background Some concepts in Mathematics and Computer Science are simple in one or t ...

  9. 2017广东工业大学程序设计竞赛决赛 题解&源码(A,数学解方程,B,贪心博弈,C,递归,D,水,E,贪心,面试题,F,贪心,枚举,LCA,G,dp,记忆化搜索,H,思维题)

    心得: 这比赛真的是不要不要的,pending了一下午,也不知道对错,直接做过去就是了,也没有管太多! Problem A: 两只老虎 Description 来,我们先来放松下,听听儿歌,一起“唱” ...

随机推荐

  1. DES加密:8051实现(C语言) & FPGA实现(VHDL+NIOS II)

    本文将利用C语言和VHDL语言分别实现DES加密,并在8051和FPGA上测试. 终于有机会阅读<深入浅出密码学一书>,趁此机会深入研究了DES加密的思想与实现.本文将分为两部分,第一部分 ...

  2. URL.createObjectURL() 与 URL.revokeObjectURL()

    .URL.createObjectURL URL.createObjectURL()方法会根据传入的参数创建一个指向该参数对象的URL. 这个URL的生命仅存在于它被创建的这个文档里. 新的对象URL ...

  3. 汽车VIN码识别适用于什么行业

    在您看完之前的文章知道了VIN码识别的原理,现在跟大家分享一下汽车VIN码识别的应用场景吧 汽车VIN码不仅在制造.销售.保养.保险.交易环节会需要录入汽车的VIN码,在交通事故处理中,作为汽车身份唯 ...

  4. 【Socket编程】Java通信是这样炼成的

    简介 网络无处不在,移动互联时代也早已到来,单机版程序慢慢的已没有生命力,所有的程序都要能够访问网络,比如 QQ 网络聊天程序.迅雷下载程序等,这些程序都要同网络打交道,本次将与各位小伙伴们分享的就是 ...

  5. 团队作业2--需求分析&原型设计

    一.需求分析 1.用户采访 a.采访对象:   分别对本学院同学.其他专业同学.部分老师等总计15人进行了采访调研: b.采访截图:    c.采访总结: (1).功能需求   能够将所提供的四个数进 ...

  6. 事后诸葛亮分析(Beta版本)

    全组讨论的照片 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 解决代码分析.统计.管理等问题,定义的很清楚,有清晰的描述. 是否有充足的时间来做计划? ...

  7. 团队作业8——第二次项目冲刺(Beta阶段)--5.21 second day

    团队作业8--第二次项目冲刺(Beta阶段)--5.21 second day Day two: 会议照片 项目进展 今天是beta冲刺的第二天,组长还在准备考试当中,我们继续做前端改进和后端安排,今 ...

  8. Swing-JTable的渲染器与编辑器使用demo

    JTable的内容.外观.事件响应在很大程度上是由渲染器与编辑器控制的.具体说来,渲染器负责单元格的外观比如前景色.背景色,以及单元格提示:编辑器负责单元格的内容和事件响应.编辑器默认为文本框形式,也 ...

  9. 201521123011 《java程序设计》 第7周学习总结

    1. 本周学习总结 参考资料: XMind 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 1.2 解释E remove(int index)源 ...

  10. 201521123013 《Java程序设计》第5周学习总结

    1. 本章学习总结 1.1 尝试使用思维导图总结有关多态和接口的知识点. 1.2可选 使用常规方法总结其他上课内容. 接口:不是类,不能使用new实例化,可用instanceof判断是否实现某接口.接 ...