题目描述
小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共mmm盆。通过调查顾客的喜好,小明列出了顾客最喜欢的nnn种花,从111到nnn标号。为了在门口展出更多种花,规定第iii种花不能超过aia_iai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。
试编程计算,一共有多少种不同的摆花方案。
输入格式
第一行包含两个正整数nnn和mmm,中间用一个空格隔开。
第二行有nnn个整数,每两个整数之间用一个空格隔开,依次表示a1,a2,…,ana_1,a_2,…,a_na1,a2,…,an。
输出格式
一个整数,表示有多少种方案。注意:因为方案数可能很多,请输出方案数对100000710000071000007取模的结果。
输入输出样例
2 4
3 2
2
说明/提示
【数据范围】
对于20%数据,有0<n≤8,0<m≤8,0≤ai≤80<n≤8,0<m≤8,0≤a_i≤80<n≤8,0<m≤8,0≤ai≤8;
对于50%数据,有0<n≤20,0<m≤20,0≤ai≤200<n≤20,0<m≤20,0≤a_i≤200<n≤20,0<m≤20,0≤ai≤20;
对于100%数据,有0<n≤100,0<m≤100,0≤ai≤1000<n≤100,0<m≤100,0≤a_i≤1000<n≤100,0<m≤100,0≤ai≤100。
NOIP 2012 普及组 第三题
【解题思路】
这一题乍一看有些难度,理解后看一下觉得其实还蛮简单的。主要思路是:先开一个二维数组b[][],存储放i种j盆花的方案总数。首先进行初始化,大家想想无论有多少种花,如果一盆都没有,那是不是只有一种方案总数了(什么也不放)?所以初始化为b[i][0]=1(0<=i<=m)。然后呢,我们进行三重循环。变量i表示有多少种花,j表示有多少盆花,k则是用于计算某种花放多少盆。从总盆数开始循环到总盆数-最大盆数,如果k小于0(说明最大盆数大于总盆数)就退出循环。我们得到的状态转移方程则是:b[i][j]+=b[i-1][k](j>=k>=j-a[i]);当然,随时加上%1000007会更保险(不要问我最后加能得多少分)。然后,然后就AC啦。
【code】
1 #include <cstdio>
2 #include <iostream>
3 #include <algorithm>
4 using namespace std;
5 const int Mod=1000007;
6 int n,m,a[105],f[105][105];
7 int main(){
8 //freopen("1077.in","r",stdin);
9 //freopen("1077.out","w",stdout);
10 scanf("%d%d",&n,&m);
11 f[0][0]=1;
12 for(register int i=1;i<=n;i++)
13 scanf("%d",&a[i]);
14 for(register int i=1;i<=n;i++)
15 for(register int j=m;j>=0;j--)
16 for(register int k=0;k<=a[i]&&j-k>=0;k++)
17 f[i][j]+=f[i-1][j-k]%Mod;
18 printf("%d\n",f[n][m]%Mod);
19 return 0;
20 }