整数分解和划分 - 兼 ACM PKU POJ 1221 解题报告

来源:互联网 发布:node.js开发cms教程 编辑:程序博客网 时间:2024/06/06 10:51

整数分解和划分是经典的数论问题,常见的有素因子分解、连续数之和及任意数之和。素因子分解就不必再多作解释;连续数之和是指把一个整数划分成多个连续或尽可能连续的整数之和,对于这个问题,笔者将另写博文介绍一二;最后一种是把一个整数划分成任意个整数之和,本文主要探讨这一种情况。

假定给定整数 N,它的一个划分是指多值集合(元素可以重复) P = {n1, n2, ..., nk | k>= 1, ni > 0 for 1<=i <= k, n1+n2+...+nk = N}。例如,{1, 1, 1} 、 {3} 和 {1, 2} 都是 整数 3 的划分。一般来说,一个整数可以存在多个划分。我们感兴趣的问题主要有:1)一个整数有多少个不同的划分? 2)给定整数 M,N 的划分中因子最大不超过(或等于) M 的划分有多少个?

关于第一个问题,在沈雷的 让面试官对你刮目相看:有多少种方法将100元兑换成零票? 一文中有很好的介绍,主要是涉及了欧拉五角数,在此不再讨论。

而第二个问题是本文的重点。令 f(n,m) 表示 n 的划分 P = {n1, n2, ..., nk | k>= 1, 0 < ni  <= m  for 1<=i <= k, n1+n2+...+nk = n} 的个数,则我们有递归方程式

        1) m == 1,则 f(n,m) = 1,也就是只有 {1, 1, ... 1 } 这种划分;

        2) m==n,则 f(n,m) = f(n, m-1) + 1,也就是除了划分 {n},在其它的划分中,元素都小于或等于 m-1;

        3) 否则,f(n,m) = f(n,m-1) + f(n-m, min(n-m,m))。

这第三种情况中,要么划分中所有元素都小于 m,要么至少有一个等于 m,而这两种子情况互不相交,因此,总的个数为两种子情况下的个数之和。

那么,这个问题和 POJ 1221 有什么关系呢?事实上,POJ 1221 的一个解法中,上述整数划分问题是它的一个子问题。POJ 1221 的大意是:回文序列是指从左向右读和从右向左读都是一样的序列。而单峰回文序列则是该序列从左和从右向中间单调非递减的序列。例如,题号 1 2 2 1 就是一个单峰回文序列,如果把每个数字看成序列的元素。现在,给定整数 n ,求 n 的单峰回文序列划分的个数。

首先,我们注意到,回文序列有两中:序列的长度为奇数和偶数的回文序列。显然,奇数 n 只可能有长度为奇数的单峰回文划分,而偶数则可以有长度为奇数的回文划分,也可以有长度为偶数的回文划分。我们先看长度为奇数的回文划分,因为这是所有整数都可以有的。

对于长度为奇数的回文划分,如果两个序列的中间的元素值不同,则两个划分肯定不同(这个不难证明)。那么,当我们固定中间元素的值为 v 时,也就是固定了中间元素左边(或右边)的序列之和 ( s = (n-v) /2,这里,取 v 使得 s 为整数 ) 时,有多少种不同的单峰回文划分呢?为了使得中间元素为 v 的回文划分是单峰的,则 s 的划分中所有元素都不能比 v 大。反过来,s 的每一个最大元素不超 v 的划分,都可以和 v 一起构成 n 的一个单峰回文划分!因此,问题就变成了求 f(s,v) !对所有可能的 (s,v) 求 f(s,v) 之和,则为 n 的长度为奇数的单峰回文划分的个数。

这样,当 n 为奇数时,问题已经得到解决。当 n 为偶数时,可以有长度为偶数的单峰回文划分。这些划分的左边之和等于右边等于 n/2。整数 s = n / 2 的每个不同的划分都可以用来构成 n 的一个不同单峰回文划分,因此,长度为偶数的单峰回文划分的个数为 f(s,s)。至此,POJ 1221 得到完满解决,而核心问题则是解决整数的划分,即求 f(n,m)。

 

许多问题初看起来似乎很复杂,但往往可以分解并化归成一些简单的或已知的或经典的问题来求解,本题即是一例。


原创粉丝点击