递归or动态规划 百炼 2749 分解因数 详细题解

 1 #define _CRT_SECURE_NO_WARNINGS  
 2 #include <stdio.h>
 3 #include <math.h>
 4 #include <algorithm>
 5 #include <stdlib.h>
 6 #include <vector>
 7 #include <map>
 8 #include <queue>
 9 #include <string>
10 #include <iostream>
11 #include <ctype.h>
12 #include <string.h>
13 #include <set>
14 #include <stack>
15 #include<functional>
16 using namespace std;
17 #define Size 22
18 #define maxn  1<<30
19 #define minn  1e-6
20 int dp[Size][Size];
21 /*
22 定义dp[i][j]  表示将i分解成不大于j的因数的个数
23 
24 i如果能分解出来j,即为i%j==0;  那么其可以由两种互斥的情况组成,
25 1,如果最终的划分结果有至少一个j 那么其种类数为dp[i/j][j](注意下次最大划分数仍是j,表示下一次仍然可以划分出 j,如果要求分解的每个数不重复,那么改为dp[i/j][j-1]即可)
26 2,如果最终的划分结果连一个j都没有,那么其种类数为dp[i][j-1]
27 比如  8%2==0  dp[8][2]=dp[4][2]+dp[8][1]
28 前面的是至少有一个2(然后把这个2划分出去,剩下的部分组合的数量是dp(4,2))  
29 后面的是没有划分出2(那么划分出来最大的数就是1)
30 
31 i如果不能分解j,即为i%j!=0 那么dp[i][j]=dp[i][j-1]
32 总结
33 if(i%j==0) 
34 dp[i][j]=dp[i][j-1]+dp[i/j][j];
35 else  
36 dp[i][j]=dp[i][j-1];
37 
38 然后寻找出口
39 1,if(j>i) dp[i][j]=dp[i][i]
40 2,dp[1][1]=dp[1][0]+dp[1][1] 
41 3,dp[2][2]=dp[2][1]+dp[1][1]=1  
42 根据上面两行推导出dp(2,1)=0  dp[1,1]=1   可以推导if(i>1) dp(i,1)=0
43 总结得到出口条件
44 i==1  return1 
45 j==1  return0
46 注意上面两行是有顺序的如果颠倒就出错了
47 */
48 int solve(int i, int j){//本题数据量太小 ,不用记录状态,递归即可直接A
49     if (i == 1) return 1;
50     if (j == 1) return 0;
51     if (i%j == 0) return solve(i / j, j) + solve(i, j - 1);
52         return solve(i, j - 1);
53 }
54 int main()
55 {
56     int n;
57     cin >> n;
58     while (n--){
59         int x;
60         cin >> x;
61         int ans = solve(x, x);
62         cout << ans << endl;
63     }
64     return 0;
65 }

 

posted @ 2018-01-29 10:41  MapReduce  阅读(544)  评论(0编辑  收藏  举报