B-icebound的商店-2018年第二届河北省大学生程序设计竞赛(DP)

icebound在得到神殿的宝藏之后,开了一家神秘的商店。你来到了商店,发现慷慨的icebound搞了
TT
T次促销活动。在每次促销活动中,icebound都会想出一个他喜欢的数字,如果你买的商品的总价刚好等于icebound喜欢的数字,那么你就可以免费得到这些商品。
icebound的商店里一共有
1515
15 件商品,商品的价格和这家商店一样神秘,第一件商品的价格是
11
1 元,第二件商品的价格是
22
2 元,设第
nn
n件商品的价格为
wnw_n
w
n

元,则:
wn=wn−1+wn−2(3≤n≤15)w_n = w_{n-1} + w_{n-2} (3 \leq n \leq 15)
w
n

=w
n−1

+w
n−2

(3≤n≤15)。
如果在某次活动中icebound喜欢的数字是
44
4,那么共有
44
4 种购买方案:

  1. 买 4个 第一种商品
  2. 买 2个 第一种商品 和 1个 第二种商品
  3. 买 2个 第二种商品
  4. 买 1个 第一种商品 和 1个 第三种商品
    请你算出共有多少种方案可以免费购物,方案数对
    10000000091000000009
    1000000009(
    =109+9=10^9+9
    =10
    9
    +9)取模。

题意:从15个斐波那契数列中找任意个数,使得这些数的和为x.求这样的方案数.

题解:打牌(DP),dp[j]表示喜欢数j的方案数.I为第I个斐波那契数列的数.状态转移方程: dp[j]=(dp[j]+d[j-a[i]])%mod;

#include <bits/stdc++.h>
using namespace std;
const int N=20;
const int M=3e3+5;
const int mod=1e9+9;
int a[N];
int dp[M];
int main(){
	a[0]=1;a[1]=1;
	for(int i=2;i<=15;i++){
		a[i]=a[i-1]+a[i-2];
	}
	int t;
	cin>>t;
	while(t--){
		memset(dp,0,sizeof(dp));
		int n;
		cin>>n;
		dp[0]=1;
		//从15个数内找任意个数(n>=1),使得这n个数的和刚好为x,求这个方案数.
		//dp,将第i个数存入时的方案数,dp[j]=dp[j]+d[j-a[i]];
		 
		for(int i=1;i<=15;i++){
			for(int j=a[i];j<=n;j++){
				dp[j]=(dp[j]+dp[j-a[i]])%mod;
			}
		}
		cout<<dp[n]<<endl;
	}
	return 0;
}
posted @ 2019-05-01 20:18  _yjun  阅读(402)  评论(0编辑  收藏  举报