考研机试 8.整数拆分
时间:2021/02/24
一.题目描述
一个整数总可以拆分为2的幂的和,例如: 7=1+2+4 7=1+2+2+2 7=1+1+1+4 7=1+1+1+2+2 7=1+1+1+1+1+2 7=1+1+1+1+1+1+1 总共有六种不同的拆分方式。 再比如:4可以拆分成:4 = 4,4 = 1 + 1 + 1 + 1,4 = 2 + 2,4=1+1+2。 用f(n)表示n的不同拆分的种数,例如f(7)=6. 要求编写程序,读入n(不超过1000000),输出f(n)%1000000000。
输入描述
每组输入包括一个整数:N(1<=N<=1000000)。
输出描述
对于每组数据,输出f(n)%1000000000。
题目链接
https://www.nowcoder.com/practice/376537f4609a49d296901db5139639ec?
tpId=40&tqId=21339&rp=1&ru=%2Fta%2Fkaoyan&qru=%2Fta%2Fkaoyan%2Fquestion-ranking&tab=answerKey
二.算法
题解
这是一个动态规划问题,重点是要找到递推式,一般不要用递归求解问题,因为可能会超时,可以通过辅助数组将递归(从上到下)转化为循环(从下到上)的形式。
递推式如下:如果n为奇数,则f(n) = f(n-1);如果n为偶数,则f(n) = f(n-1) + f(n/2)。
下面是一个大佬对递推式的分析过程:(主要通过划分奇拆分和偶拆分来求解)
思路:通过递推公式,划分为子问题求解。问题:一个整数拆分为2的幂的和。即(1, 2, 2^2, 2^3,..., 2^k),包含1个奇数和k个偶数。对于N,分为两种情况:1)N为奇数(2m+1),则每个拆分结果必然至少有一个1,因为只通过k个偶数无法组成奇数。所以f(2m+1) = f(2m)例如 f(5) 1 + (4) 1 + (2+2) 1 + (1+1+2) 1 + (1+1+1+1+1)f(4) 4 2+2 1+1+2 1+1+1+1+12) N为偶数(2m),拆分同样分为两类:拆分结果中包含1和拆分结果不包含1a) 拆分结果包含1 (奇拆分):所有的拆分数目为f(2m-1),同上b) 拆分结果不包含1(偶拆分):拆分数目为f(m)。 拆分结果不包含1,说明是拆分成了k个偶数,那么对每一种拆分结果都除以2,并不会影响整体拆分的数目。但是每个拆分结果的sum都变成了m,即每个2m的偶拆分都变成了m的拆分。同样对m的每种拆分结果都乘以2,拆分结果的sum都变成了2m且不包含1。即m的拆分和2m的偶拆分一一对应。例如 f(8) (不包含1的拆分有四种) 8 4+4 2+2+4 2+2+2+2f(4)(所有拆分有四种) 4 2+2 1+1+2 1+1+1+1f(2m) = f(2m-1) + f(m)综上所述:f(2m+1) = f(2m)f(2m) = f(2m-1) + f(m)
重点
动态规划
代码
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); int max = 1000001; int[] count = new int[max]; count[1] = 1; count[2] = 2; for(int i = 3; i < max; i++){ if(i % 2 == 1){ count[i] = (count[i - 1] % 1000000000); } else{ count[i] = ((count[i - 1] + count[i / 2]) % 1000000000); } } while(in.hasNext()){ int n = in.nextInt(); System.out.println(count[n]); } in.close(); } }
努力,向上,自律