題意: 問k個數可以形成sum=n, LCM = m的數量 (n,m<=1000, k<=100)
思路: dp[i+1][j+v][lcm(k, v)] += dp[i][j][k].... 然後。。。需要各種優化。。。。 坑。。。
#include <bits/stdc++.h>
using namespace std;
int n,m,k;
const int mod = 1e9+7;
int dp[2][1011][1011];
vector<int> in;
int lcm[1010][1010];
void init(){
in.clear();
int tmp = m;
for(int i = 1; i<=tmp; i++)
if(tmp%i == 0)
in.push_back(i);
}
int main(){
for(int i=1; i<=1000; i++)
for(int j=i; j<=1000; j++)
lcm[i][j]=lcm[j][i] = i/__gcd(i, j)*j;
while(scanf("%d %d %d", &n, &m, &k)!=EOF){
init();
for(int i=0; i<=1; i++)
for(int j=0; j<=n; j++)
for(int o=0; o<=m; o++)
dp[i][j][o] = 0;
int size = in.size();
int tmp = 0;
for(int i=0; i<size; i++)
dp[tmp][in[i]][in[i]] = 1;
for(int i=1; i<k; i++){
for(int j=1; j<=n; j++)
for(int o=1; o<=m; o++)
dp[tmp^1][j][o] = 0;
for(int j=1; j<=n; j++){
for(int oo=0; oo<size; oo++){
if(dp[tmp][j][in[oo]] == 0) continue;
for(int p=0; p<size; p++){
int o = in[oo];
int v = in[p];
int t = lcm[v][o];
if(t > m) continue;
if(j + v > n) continue;
dp[tmp^1][j+v][t] += dp[tmp][j][o];
if(dp[tmp^1][j+v][t] >= mod)
dp[tmp^1][j+v][t] -= mod;
}
}
}
tmp ^= 1;
}
printf("%d\n", dp[tmp][n][m]);
}
return 0;
}