【2012 Asia ChangChun Regional Contes】 [Math Magic] 动态规划

题目链接: https://acm.hdu.edu.cn/showproblem.php?pid=4427

解法:

  1. 题目m范围较小$m\leq 1000$,n 范围也较小 $n\leq 1000$, $k\leq 100$
  2.  可以枚举m的约数,很容易知道不会超过32个。
  3. 对于$\sum factor[i]= m$。类似背包,考虑dp[n][lcm][k]为结果,显然有递推式$\forall j \in \left [ 0,factors.length \right ) $   dp[ sum+ factor[j] ][  LCM( factor[i],factor[j]) ] [k+1] +=  dp[sum][factor[i]][k]
  4. 如果采用三维,容易超出内存,考虑使用滚动数组
  5. 代码如下

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.*;

public class Main {
    static int MOD = 1_000_000_007;

    public static void main(String[] args) throws IOException {
        StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
//        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
        while (st.nextToken() != StreamTokenizer.TT_EOF) {
            int n, m, k;
            n = (int) st.nval;
            st.nextToken();
            m = (int) st.nval;
            st.nextToken();
            k = (int) st.nval;
            List<Integer> factorlist = getFactor(m);


            process(n, m, k, factorlist);

        }
//        out.flush();
    }

    public static void process(int n, int m, int k, List<Integer> factlist) {
        factors = factlist.toArray(new Integer[factlist.size()]);
        index = new int[1001];
        for (int i = 0; i < factors.length; i++) {
            index[factors[i]] = i;
        }

        _LCM = new int[factors.length][factors.length];
        for (int i = 0; i < factors.length; i++) {
            for (int j = 0; j < factors.length; j++) {
                _LCM[i][j] = LCM(factors[i], factors[j]);
            }
        }

        long ret = dp(n, m, k);
        System.out.println(ret);
    }

    public static int LCM(int a, int b) {
        return a * b / gcd(a, b);
    }

    public static int gcd(int a, int b) {
        if (a % b == 0) {
            return b;
        }
        return gcd(b, a % b);
    }


    static int[] index;

    static int[][] _LCM;
    static Integer[] factors;


    public static long dp(int n, int m, int k) {
        long[][] mem = new long[n + 1][factors.length];
        for (int i = 0; i < factors.length; i++) {
            if (factors[i] <= n) {
                mem[factors[i]][i] = 1;
            }
        }

        for (int step = 1; step < k; step++) {
            long[][] next = new long[n + 1][factors.length];
            for (int sum = 1; sum <= n; sum++) {
                for (int i = 0; i < factors.length; i++) {
                    if (mem[sum][i] <= 0) {
                        continue;
                    }
                    for (int j = 0; j < factors.length && sum + factors[j] <= n; j++) {
                        next[sum + factors[j]][index[_LCM[i][j]]] += mem[sum][i];
                        next[sum + factors[j]][index[_LCM[i][j]]] %= MOD;
                    }
                }
            }
            mem = next;
        }
        return mem[n][index[m]];
    }

    public static List<Integer> getFactor(int n) {
        List<Integer> list = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            if (n % i == 0) {
                list.add(i);
            }
        }
        return list;
    }
}

 

posted @ 2024-03-16 20:29  fishcanfly  阅读(17)  评论(0)    收藏  举报
//雪花飘落效果