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 }