1693: 【基础】奶牛沙盘队

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:13 解决:1

题目描述

Farmer Han开始玩飞盘之后,YDS也打算让奶牛们享受飞盘的乐趣.他要组建一只奶牛飞盘队.他的N(1≤N≤2000)只奶牛,每只奶牛有一个飞盘水准指数Ri(1≤Ri≤100000).YDS要选出1只或多于1只奶牛来参加他的飞盘队.由于YDS的幸运数字是F(1≤F≤1000),他希望所有奶牛的飞盘水准指数之和是幸运数字的倍数.

帮YDS算算一共有多少种组队方式.组队方式数模10^8取余的结果.

输入

第1行输入N和F,之后N行输入Ri

输出

组队方式数模10^8取余的结果

样例输入 复制

4 5 
1
2 
8 
2

样例输出 复制

3

提示

这就是一个类似于lns="http://www.w3.org/1998/Math/MathML">01背包的问题。对于每头牛都有取和不取两种选择。

lns="http://www.w3.org/1998/Math/MathML">[][]表示在前lns="http://www.w3.org/1998/Math/MathML">头牛中选择,所选数之和lns="http://www.w3.org/1998/Math/MathML"> 结果为lns="http://www.w3.org/1998/Math/MathML">的方案数。(以下用“和为lns="http://www.w3.org/1998/Math/MathML">”表示“和lns="http://www.w3.org/1998/Math/MathML"> 结果为lns="http://www.w3.org/1998/Math/MathML">”。)

  • 若不取lns="http://www.w3.org/1998/Math/MathML">,则应在前lns="http://www.w3.org/1998/Math/MathML">1头牛中取来若干和为lns="http://www.w3.org/1998/Math/MathML">的数,方案数即为lns="http://www.w3.org/1998/Math/MathML">[1][]
  • 若取lns="http://www.w3.org/1998/Math/MathML">,则应在前lns="http://www.w3.org/1998/Math/MathML">1头牛中取来若干和为lns="http://www.w3.org/1998/Math/MathML">[]的数,这样加上lns="http://www.w3.org/1998/Math/MathML">[]后,和才能等于lns="http://www.w3.org/1998/Math/MathML">,即lns="http://www.w3.org/1998/Math/MathML">[1][[]]

所以lns="http://www.w3.org/1998/Math/MathML">[][]=[][]+[1][]+[1][[]]

这里还有一个关于取模的问题要解决。我们要用到的只是lns="http://www.w3.org/1998/Math/MathML">[]  的余数,所以输入时就先将lns="http://www.w3.org/1998/Math/MathML">[]lns="http://www.w3.org/1998/Math/MathML">取模。
还有就是lns="http://www.w3.org/1998/Math/MathML">[]可能为负数,这时就得写成(j-r[i]+F)%F,就为正了。

初始化lns="http://www.w3.org/1998/Math/MathML">[][[]]lns="http://www.w3.org/1998/Math/MathML">1

#include<bits/stdc++.h>
const int p=1e8;//定义常数
const int N=2000+10;
const int F=1000+10;
using namespace std;

int n,f,r[N],s[N][F];
long long h[N][F];

int main()
{
	int i,j;
	cin>>n>>f;
	for(i=1;i<=n;i++)
	{
	  cin>>r[i];
	  r[i]%=f;//提前取模
	}
	for(i=1;i<=n;i++) h[i][r[i]]=1;//初始化
	for(i=1;i<=n;i++)
	  for(j=0;j<f;j++)//余数范围:0到f-1
	    h[i][j]=((h[i][j]+h[i-1][j])%p+h[i-1][(j-r[i]+f)%f])%p;//每加一次就%p
	cout<<h[n][0]<<endl;
	return 0;
}