zoukankan      html  css  js  c++  java
  • hiho1096_divided_product

    题目

        给出两个正整数N和M, N <= 100, M <= 50, 可以将N分解成若干个不相等的正整数A1, A2... Ak的和,且A1, A2 ... Ak的乘积为M的倍数。即 
    N = A1 + A2 + ... + Ak; 
    A1*A2*...Ak % M = 0; 
    求可以有多少种分解方式? 
    题目链接: divided product

    分析

        直接DFS搜索,DFS(cur_sum, cur_max_num, cur_product) 枚举出总和为N的,且各个数字不断增加的方案,然后判断他们的乘积是否等于M的倍数。实现复杂度为:(2^t, t 为几十的量级),显然不行; 
    考虑动态规划来解决: 
        维护状态 dp[i][j][t] 表示 A1,A2...Ak的总和为i,且最大的数字Ak等于j,A1*A2..A*k的结果模M为t的分解方案总个数。 
    则可以有递推公式:

    1. int tt = k*t%M;
    2. dp[i + k][k][tt] += dp[i][j][t];
    3. dp[i + k][k][tt] %= mod;

    其中需要注意 边界条件 dp[i][i][i%M] = 1.

    实现

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<string>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<unordered_map>
    #include<unordered_set>
    #include<algorithm>
    using namespace std;
    int dp[105][105][55];
    int main(){
    	const int mod = 1000000007;
    	int n, m;
    	scanf("%d %d", &n, &m);
    	memset(dp, 0, sizeof(dp));
    	for (int i = 0; i <= n; i++){
    		for (int j = 0; j <= i; j++){
    			for (int k = j + 1; (k + i) <= n; k++){
    				for (int t = 0; t < m; t++){
    					if (i == 0)
    						dp[k][k][k%m] = 1;
    					else{
    						int tt = k*t%m;
    						dp[i + k][k][tt] += dp[i][j][t];
    						dp[i + k][k][tt] %= mod;
    					}
    				}
    			}
    		}
    	}
    	int result = 0;
    	for (int i = 1; i <= n; i++)
    		result = (result + dp[n][i][0]) % mod;
    	printf("%d
    ", result);
    	return 0;
    }
    
  • 相关阅读:
    高性能网站优化-确保异步加载脚本时保持执行顺序
    sublime安装和汉化
    解决IE6下a标签的onclick事件里的超链接不跳转问题
    C++大数据处理
    HDRtools-OpenExr
    Effective C++学习进阶版
    我的算法学习之路
    一个应届计算机毕业生的2012求职之路
    存储器管理
    程序员的自我修养——操作系统篇
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/5602587.html
Copyright © 2011-2022 走看看