1120: 划分数

Time Limit: 8 Sec  Memory Limit: 128 MB
Submit: 6  Solved: 3
[Submit][Status][Web Board]

Description

有n个无区别的物品,将它们划分成不超过m组,求出划分方法数模M的余数。

限制条件

1 <= m <= n <= 1000

2 <= M <= 10000

Input

每组测试数据输入一行n, m, M。

Output

输出划分数模M的余数。

Sample Input

42 468 6335

Sample Output

2494

HINT

组合数学

Source

可以将问题转变成x1+x2+x3+x4+x5+x6+.....xk+.....xm=n; <=xk;
这类问题一般有这样的限制:每个数的最大值,最小值,每个数是否可以相同.
相当于求不定方程x的非负整数解,但是n等于4时1 2和1 1根据题意,物品是相同的,所以这两种是一样的,
所以不能用校赛那道球放盒子的那种方式,
(考虑第i个盒子,放k个,d[i][j]+=d[i-][j-k];<=k<=m),
从整体进行考虑,对于每一个减去1,由于最小数可能为0,所以有两种情况,一种是最小数为0,一种是最小数为1,
d[m][n]=d[m][n-t]+d[m-][n],最小数为1,减去一,最小数为0,直接去掉0。,初始化d[][]=,
这种方式为什么可以去重呢?
当有多个最小值为0时,由于去0时没有考虑去掉的是哪一个,所以去0操作跟位置没有关系。
(最小数为0,可能有多个,假设是k个,去k次,跟位置无关,去k次就可去完)
假设这个数是0,0,2,不考虑位置的去0,所以可以去重.
将n个数划分为m个不同的正整数解,且最大值小于n
  f1[t][x]=f[t][x-t]+f[t-][x-t]-f[t-][x-(n+)]
将n个数划分为m个不同的正整数解      
  f2[t][x]=f2[t][x-t]+f2[t-][x-t]
下面这两种情况去掉了1 2和1 1类似的重复情况。  
将n个数划分为m个非空集合     
   f3[t][x]=f[t][x-t]+f[t-][x-]
  (最小数为1,去掉一个,如果最小数有多个,由于没有考虑去掉的是哪一个,所以1 , 1是相同的情况)
将n个数划分为m个可为空的集合     
  d[m][n]=d[m][n-m]+d[m-][n]
  (最小数为0,可能有多个,假设是k个,去k次,跟位置无关,去k次就可去完)
   d[m][n]=f3[][n]+f3[][n]+f3[][n]+.....f[k][n]+....f[m][n];
扩展问题:
    有n种物品,第i种物品有a[i]个,不同种类的物品可以互相取分,但相同种类的无法区分,
    从这些物品中取出m个的话,有多少种取法?
解法1
      d[i+][j]
      代表将前i种物品中取出j个,并且每种物品最多去a[i]个,
    d[i+][j]+=d[i][j-k] <=k<=min(j,a[i]);
解法2
    d[i+][j]=d[i+][j-]-d[i][j--a[i]]+d[i][j]
    要求得是从前i个物品中取出j个的方案数,由于此题中1 1 2和1 2 1这两种是不同的,
    所以不用考虑重复,这样就不能给每个数都减去1,我们可以考虑给第i个数减去1,
    a:  当第i个数>=1时,d[i+1][j-1]等于d[i+1][j],然而第i个数的最大值要小于等于a[i],
      再正着看回去,d[i+1][j-1]肯定满足条件,如果给它的第i个数等于a[i],加上1之后,
       d[i+1][j]就不满足条件了,所以需要减去d[i][j-1-a[i]];
    b: 当第i个数等于0时,d[i][j]=d[i+1][j].
#include <iostream>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
#define maxn 1100
int n,m,MOD;
int d[maxn][maxn];
void init()
{
memset(d,,sizeof(d));
/* for(int i=1;i<=maxn;i++)
{
d[i][1]=1;
d[i][0]=1;
}*/ }
void solve()
{
d[][]=;
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
{
if(j>=i)
d[i][j]=(d[i][j-i]+d[i-][j])%MOD;
else
d[i][j]=d[i-][j]%MOD;
}
printf("%d\n",d[m][n]);
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&MOD))
{
init();
solve();
}
return ;
}

扩展问题的代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define maxn 1100
int n,m;
int a[maxn];
int dp[maxn][maxn];
int MOD;
void init()
{
// memset(a,0,sizeof(a));
// memset(dp,0,sizeof(dp));
}
void solve()
{
for(int i=;i<=n;i++)
dp[i][]=; for(int i=;i<n;i++)
for(int j=;j<=m;j++)
{
if(j--a[i] >= )
{
dp[i+][j]=(dp[i+][j-] + dp[i][j] -dp[i][j--a[i] ] + MOD) %MOD;
}
else
dp[i+][j]=(dp[i+][j-] + dp[i][j] ) %MOD;
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
printf("%d ",dp[i][j]);
printf("\n");
}
}
int main()
{
// freopen("test.txt","r",stdin);
while(~scanf("%d%d%d",&n,&m,&MOD))
{
init();
for(int i=;i<n;i++)
scanf("%d",&a[i]);
solve();
}
return ;
}

snnu1120: 划分数(DP计数问题)的更多相关文章

  1. HDU 4832(DP+计数问题)

    HDU 4832 Chess 思路:把行列的情况分别dp求出来,然后枚举行用几行,竖用几行.然后相乘累加起来就是答案 代码: #include <stdio.h> #include < ...

  2. 划分数 (DP)

    输入: n=4 m=3 M=10000 输出: 4 (1+1+2=1+3=2+2=4) 复杂度(nm) int n,m; int a[MAX]; int dp[MAX][MAX]; //数组 void ...

  3. 5.15 牛客挑战赛40 C 小V和字符串 数位dp 计数问题

    LINK:小V和字符串 容易想到只有1个数相同的 才能有贡献. 知道两个01串 那么容易得到最小步数 大体上就是 第一个串的最前的1和第二个串最前的1进行匹配. 容易想到设f[i][j]表示 前i位1 ...

  4. HDU 4489 The King’s Ups and Downs (DP+数学计数)

    题意:给你n个身高高低不同的士兵.问你把他们按照波浪状排列(高低高或低高低)有多少方法数. 析:这是一个DP题是很明显的,因为你暴力的话,一定会超时,应该在第15个时,就过不去了,所以这是一个DP计数 ...

  5. [HEOI2014]平衡(整数划分数)

    下课了,露露.花花和萱萱在课桌上用正三棱柱教具和尺子摆起了一个“跷跷板”. 这个“跷跷板”的结构是这样的:底部是一个侧面平行于地平面的正三棱柱教具,上面 摆着一个尺子,尺子上摆着若干个相同的橡皮.尺子 ...

  6. 51NOD 1154 回文串的划分(DP)

    思路:参考了网上,思路很清奇,借助vis[i][j]来表示从i到j是否为回文串,回文串这边是用的双重循环来写的:dp[i]用来表示以i结尾的字符串最少的回文串有多长. #include<cstr ...

  7. Day9 - K - Yue Fei's Battle HDU - 5136

    Yue Fei is one of the most famous military general in Chinese history.He led Southern Song army in t ...

  8. Noip模拟42 2021.8.17

    T1 卷 一看跟没有上司的舞会一样,直接敲了然后试个自己造的样例对了就跑了... 然而把它想简单了,乘积取模,还能比大小吗????? 显然不能 所以直接让对数的加和跟着$dp$直接一起跑,比大小的都用 ...

  9. 2021.8.17考试总结[NOIP42]

    $\huge{取模不能比大小!}$ $\huge{取模不能比大小!}$ $\huge{取模不能比大小!}$ 有了打地鼠的前车之鉴,我深信树规板子是可以出现在联赛题里的. 所以T1十分钟码完直接溜了,后 ...

随机推荐

  1. mybatis使用步骤

    1.创建config.xml文件.设置环境.数据源等: 2.设置mapper.xml文件.写sql:下面图中的resultType属性经常会替换为resultMap,不过需要加入<resultM ...

  2. [Vijos] SuperBrother打鼹鼠

    背景 SuperBrother在机房里闲着没事干(再对比一下他的NOIP,真是讽刺啊......),于是便无聊地开始玩“打鼹鼠”...... 描述 在这个“打鼹鼠”的游戏中,鼹鼠会不时地从洞中钻出来, ...

  3. BZOJ1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害

    n<=3000个点m<=20000条无向边的图,有p<=n个出发点,每个出发点都不可拆,现拆一些点使每个出发点都不能到达点1,求最小点数. 简单的最小割.每个点拆成两个x和y,无向边 ...

  4. Linux MTD (Memory Technology Device) subsystem analysis -For Atheros char device

    Linux MTD (Memory Technology Device) subsystem analysis For Atheros char device 读了Linux MTD 源代码分析 对这 ...

  5. Linux 端口开放

    Linux(CentOS): 系统缺省值为32768-61000. 修改方法: 在/etc/sysctl.conf中,增加以下配置:(开放20000-50000为完成端口) net.ipv4.ip_l ...

  6. Pick-up sticks--poj2653(判断两线段是否相交)

    http://poj.org/problem?id=2653 题目大意:有n根各种长度的棍   一同洒在地上 求在最上面的棍子有那几个 分析:  我刚开始想倒着遍历  因为n是100000   想着会 ...

  7. 分享一下然让显卡满血复活的小技巧(GTX)

    分享一下然让显卡满血复活的小技巧 笔者在玩大型游戏卡顿15fps下载如下操作 GTX950玩大型游戏都不会卡帧率稳定在30fps 下载GeForce Experience下载更新最新驱动 下载如下程序 ...

  8. kis

    http://5.xp510.com:801/xp2011/%E9%87%91%E8%9D%B6kis%E4%B8%93%E4%B8%9A%E7%89%88.rar

  9. 多线程调用COM组件的体会(CoInitialize)

    调用任何COM组件之前,你必须首先初始化COM套件环境,即调用CoInitialize或CoInitializeEx.COM套件环境在线程的生存周期内有效,线程退出前需要调用CoUninitializ ...

  10. C# 谁改了我的代码 使用 Resharper 快速做适配器

    C# 谁改了我的代码   本文告诉大家一个特殊的做法,可以修改一个字符串常量 我们来写一个简单的程序,把一个常量字符串输出 private const string str = "linde ...