Yesterday, my teacher taught us about math: +,-, *,/, GCD, LCM ... As you know, LCM (Least Common multiple) of the positive numbers can be solved easily because of a * b = GCD (A, b) * LCM (A, B).
In class, I raised a new idea: "How to calculate the LCM of K numbers". It's also an easy problem indeed, which only cost me 1 minute to solve it. I raised my hand and told teacher about my outstanding algorithm. Teacher just smiled and smiled ...
After class, my teacher gave me a new problem and he wanted me solve it in 1 minute, too. If We know three parameters N, M, K, and both equations:
1. SUM (A1, A2, ..., Ai, ai+1,..., AK) = N
2. LCM (A1, A2, ..., Ai, ai+1,..., AK) = M
Can calculate how many kinds of solutions is there for AI (AI is all positive numbers). I began to roll cold sweat but teacher just smiled and smiled.
Can you solve this problem in 1 minute?
Input
There is multiple test cases.
Each test case contains three integers N, M, K. (1≤n, m≤1,000, 1≤k≤100)
Output
For each test case, output an integer indicating the number of solution modulo 1,000,000,007 (1e9 + 7).
You can get more details in the sample and hint below.
Sample Input
4 2 23) 2 2
Sample Output
12
Test instructions
Give n,m,k, ask K number of and is n, least common multiple for m of case there are several
Ideas:
Because least common multiple is m, you can know that these numbers are necessarily m factors, then we just need to select all of these factors, take these factors to the backpack can be
Dp[i][j][k] indicates that the number of I has been placed, and the case of J, common multiple K has several
But the problem, the first problem of memory, direct memory explosion, then we need to optimize
1. Because I put the number I now, it must be based on the number of i-1 to be calculated, we only need to use a rolling array to solve the
2. For common multiple, must not be more than M, and I all of these m factor of the number, no matter what to choose, how much to choose, their least common multiple is still among these factors, then we can be discretized
After we've solved it, it's a complete backpack problem.
#include <stdio.h> #include <algorithm> #include <string.h> #include <vector> #include < math.h>using namespace Std;const int mod = 1e9+7;int dp[2][1005][105];int a[1005],len,pos[1005];int n,m,k;int hash[ 1005][1005];int gcd (int a,int b) {return b==0?a:gcd (b,a%b);} int LCM (int a,int b) {return a/gcd (b) *b;} int main () {int i,j,x,y; for (i = 1; i<=1000; i++)//preprocessing least common multiple {for (j = 1; j<=1000; j + +) Hash[i][j] = LCM (I,J); } while (~SCANF ("%d%d%d", &n,&m,&k)) {len = 0; memset (Pos,-1,sizeof (POS)); for (i = 1; i<=m; i++) {if (m%i==0) {A[len] = i; Pos[i] = len++;//discretization}} memset (Dp[0],-1,sizeof (dp[0])); Dp[0][0][0] = 1; for (i = 1; i<=k; i++) {memset (dp[i%2],-1,sizeof (dp[i%2])); for (j = i-1; j<=n; j + +)//Because the minimum must be 1, and I have already put the number of i-1, the front and the least must be i-1 { for (x = 0; x<len; x + +)//Enumerate the common multiple {if (dp[(i+1)%2][j][x]==-1) of the preceding digits Continue for (y = 0; Y<len && (a[y]+j) <=n; y++)//Enumerate what number of this bit {int r = hash[a[ Y]][A[X]]; int s = j+a[y]; if (pos[r]!=-1 && r<=m) {r = Pos[r]; if (dp[i%2][s][r] = =-1) dp[i%2][s][r] = 0; dp[i%2][s][r]+=dp[(i+1)%2][j][x]; Dp[i%2][s][r]%=mod; }}}}} if (Dp[k%2][n][pos[m]]==-1) printf ("0\n"); else printf ("%d\n", Dp[k%2][n][pos[m]]); } return 0;}
Zoj3662:math Magic (Full backpack)