【2012 Asia ChangChun Regional Contes】 [Math Magic] 动态规划
题目链接: https://acm.hdu.edu.cn/showproblem.php?pid=4427
解法:
- 题目m范围较小$m\leq 1000$,n 范围也较小 $n\leq 1000$, $k\leq 100$
- 可以枚举m的约数,很容易知道不会超过32个。
- 对于$\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]
- 如果采用三维,容易超出内存,考虑使用滚动数组
- 代码如下
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; } }

浙公网安备 33010602011771号