hdu 4427 三維dp

題意: 問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;
}

 
發佈了58 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章