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 种购买方案:
- 买 4个 第一种商品
- 买 2个 第一种商品 和 1个 第二种商品
- 买 2个 第二种商品
- 买 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;
}