题目链接

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. H5性能测试学习

    工欲善其事,必先利其器,在做H5前端性能测试之前,选择合适的工具能让我们的测试工作事半功倍.本文要提到的工具有两类: 一类是抓包工具,如Fiddler.Charles等.这类工具不仅可以抓包,还可以对 ...

  2. SSH2项目网上书店系统手把手教学_Struts2+Spring+Hibernate整合开发

    一 序言 鉴于目前J2EE的火热程度,SSH2是每个学生毕业前都必须掌握的一门技术,所以在这里我就使用SSH2技术做一个小型项目,和大家一起学习. SSH2技术的基础概论就不再提了,直接说特点吧. 1 ...

  3. 为Markdown文件生成目录

    缘由 思路 效果 代码实现 缘由 Markdown源生文件源生不支持目录,目前比较主流的生成目录的方式(各式插件),都是转化为HTML文件.虽然HTML文件可以生成眼花缭乱的目录,但是修改起来又没有M ...

  4. 【译】怎样处理 Safari 移动端对图片资源的限制

    原文作者:Thijs van der Vossen 本文翻译自<How to work around the Mobile Safari image resource limit>,原文写 ...

  5. ASP.NET Core的身份认证框架IdentityServer4(7)- 使用客户端证书控制API访问

    前言 今天(2017-9-8,写于9.8,今天才发布)一口气连续把最后几篇IdentityServer4相关理论全部翻译完了,终于可以进入写代码的过程了,比较累.目前官方的文档和Demo以及一些相关组 ...

  6. 如何快速把 Vue 项目升级到 webpack3

    由于 webpack3升级后,新增了 Scope Hositing(作用域提升) 功能,据说是对 js的性能提升很大.因此,我们做了一个测试对比,就是 webpack3和 webpack1/2 的性能 ...

  7. poj 2063完全背包

    题意:给出总资金和投资年份 ,n个股票 给出股票价格和其一年的利润.问如何选择能获得最大利润. 思路:股票可以重复选择,完全背包问题,完全背包也是从01背包衍生而行的,其主要区别在于中间那层循环的次序 ...

  8. c# 网页打印全流程

    说明:我要实现的就是将数据库中Group表的数据查找出来,替换打印模版中的内容,再将模版文件打印出来 1.准备好要打印的模版group_O_train.html <div class=" ...

  9. 201521123103 《Java学习笔记》 第八周学习总结

    一.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 集合部分:TreeMap实现类:对键值进行排序. Map的entrySet Set<Map.Entry&l ...

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

    1. 本周学习总结 2. 书面作业 1. 代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 不能 ...