https://www.luogu.com.cn/problem/P1025
Title Description
The integer n into k parts, and each can not be empty, any two schemes are different (regardless of order).
For example: n-=. 7 , K =. 3 , the following three sub-methods are considered the same.
1,1,5;
1,5,1;
5,1,1.
Q. How many different points system.
Input Format
n,k (6<n≤200,2≤k≤6)
Output Format
. 1 integer, i.e., different points system.
Sample input and output
7 3
4
Description / Tips
Four kinds of points of law:
1,1,5 ;
1,2,4 ;
1,3,3 ;
2,2,3 .
A solution (DFS):
DFS is relatively easy to think of, but need pruning.
void DFS(int sum,int step,int k)
k denotes the number of points on a, this time from the beginning of the k points, sum represents by far was divided into a number, step represents a far divided the number of copies.
Since the program number is not the same, so to keep the enumeration of the number of increments (or decreasing), we can carry out repetitive pruning, record k (on how many points a), this time from the start of k points.
We also prune feasibility, as long as each enumerated from i to k i * (m - step) <= n-sum on it.
Because the next minute value smaller than the current i can not, after all is assumed that each sub-i, then if i * (m - step)> n-sum, then the remaining value is not enough points, not just the current i the line, no need to continue the DFS.
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 const int MOD = 1E9 + . 7 ; 16 const int MAXN = 1E4 + 10 ; . 17 the using namespace STD; 18 is . 19 int n-, m; 20 is int ANS; 21 is 22 is void the DFS ( int SUM, int STEP, int K) // K represents the assigned a number, repetitive pruning 23 is { 24 IF (STEP == m) 25 { 26 is IF (SUM n-==) ANS ++ ; 27 return ; 28 } 29 for(int i=k;i*(m-step)<=n-sum;i++)//可行性剪枝 30 DFS(sum+i,step+1,i); 31 } 32 33 int main() 34 { 35 #ifdef DEBUG 36 freopen("sample.txt","r",stdin); 37 #endif 38 39 scanf("%d %d",&n,&m); 40 DFS(0,0,1); 41 printf("%d\n",ans); 42 43 return 0; 44 }
Solution two (DP):
DP [i] [j] denotes the integer i is divided into the number of program parts j.
First, if a get integer i, as the title of each claim is not empty, it must first come up to position number j j 1 parts are placed, then the remaining i - j number.
Then the remaining number of how to handle it? May be assigned to all of them a (dp [ij] [1]), may be assigned in duplicate (dp [ij] [2]), ..., j may be assigned to the parts (DP [ ij] [j]), each of a points all together, and that is dp [i] [j].
But this formula does not seem simple, in order to obtain a simple formula, we then seek a dp [i-1] [j-1],
Comparison of the above two equations can be obtained,
Two cases corresponding to the formula:
1. There are only a fraction of a 1, the remaining i-1 j-1 to be divided into parts corresponding to dp [i-1] [j -1].
2. Each value is greater than 1, i.e. in the parts of the first j in each copy to put a 1, then a ij left, then a ij which it then distributed to the j parts, corresponding to DP [ij ] [j]. (At this point I must be greater than i j)
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 const int mod=1e9+7; 16 const int maxn=1e4+10; 17 using namespace std; 18 19 int dp[205][10]; 20 21 int main() 22 { 23 #ifdef DEBUG 24 freopen("sample.txt","r",stdin); 25 #endif 26 27 int n,m; 28 scanf("%d %d",&n,&m); 29 for(int i=1;i<=n;i++) 30 { 31 dp[i][1]=1; 32 for(int j=2;j<=m;j++) 33 { 34 if(i==j) dp[i][j]=1; 35 else if(i>j) dp[i][j]=dp[i-1][j-1]+dp[i-j][j]; 36 } 37 } 38 printf("%d\n",dp[n][m]); 39 40 return 0; 41 }
-