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;
}