1899: Yuelu Scenes
Submit Page Summary Time Limit: 1 Sec Memory Limit: 256 Mb Submitted: 4 Solved: 3
Description
An artist begins with a roll of ribbon, one inch wide. She clips it into pieces of various integral lengths, then aligns them with the bottom of a frame, rising vertically in columns, to form a Yuelu scene. A Yuelu scene must be uneven; if all columns are the same height, it’s a plain scene, not a Yuelu scene! It is possible that she may not use all of the ribbon.
If our artist has 4 inches of ribbon and a 2 × 2 inch frame, she could form these scenes:
She would not form these scenes, because they’re plains, not mountains!
Given the length of the ribbon and the width and height of the frame, all in inches, how many different Yuelu scenes can she create? Two scenes are different if the regions covered by ribbon are different. There’s no point in putting more than one piece of ribbon in any column.
Input
Each input will consist of several case. Each input will consist of a single line with three space-separated integers n, w and h, where n (0 n ≤ 10,000) is the length of the ribbon in inches, w (1 ≤ w ≤ 100) is the width and h (1 ≤ h ≤ 100) is the height of the frame, both in inches.
Output
Output a single integer, indicating the total number of Yuelu scenes our artist could possibly make, modulo 1e9 + 7.
Sample Input
25 5 5
15 5 5
10 10 1
4 2 2
Sample Output
7770
6050
1022
6
Hint
Source
中南大学第十一届大学生程序设计竞赛
题目大意:用
n∗1
的缎带覆盖
w∗h
的矩形,不能超出其范围(可以任意剪裁缎带,长度为整数),且最后覆盖的形状每一列的行高不能完全一致,总共有多少种排列方法?
解题思路: dp[i][j] 表示用了
i∗1
的缎带覆盖了j的宽度有多少种情况,包括行高相同的情况
dp[i][j]=dp[i][j-1]+dp[i-1][j-1]+…+dp[i-h][j-1]
但这样时间复杂度是O(nwh),是不行的
我们发现填表时,计算的是连续的一段,
故计算第j列时,统计第j-1列的前缀和sum[i]
那么
if(i-h-1>=0) dp[i][j]=(sum[i]-sum[i-h-1])%MOD;
else dp[i][j]=sum[i]%MOD;
每次改变列都要更新sum,
最后将行高都相等的情况减掉就可以啦~
考查内容:动态规划,前缀和优化
时间复杂度: O(nw)
题目难度: ★★★★
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int MOD=1e9+7;
LL dp[10005][105];
LL sum[10005];
int n,w,h;
void init()
{
memset(dp,0,sizeof(0));
memset(sum,0,sizeof(sum));
for(int j=0;j<=w;j++)
dp[0][j]=1;
for(int i=0;i<=n;i++)
dp[i][0]=1;
}
void update(int j)
{
sum[0]=dp[0][j];
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+dp[i][j];
}
int main()
{
ios::sync_with_stdio(false);
while(cin>>n>>w>>h)
{
init();
for(int j=1;j<=w;j++)
{
update(j-1);
for(int i=1;i<=n;i++)
{
if(i-h-1>=0) dp[i][j]=(sum[i]-sum[i-h-1])%MOD;
else dp[i][j]=sum[i]%MOD;
}
}
/*cout<<endl;
for(int i=0;i<=n;i++)
{
for(int j=0;j<=w;j++)
{
cout<<dp[i][j]<<" ";
}
cout<<endl;
}*/
if(n>=w*h) dp[n][w]-=(h+1);
else dp[n][w]-=(n/w+1);
cout<<dp[n][w]<<endl;
}
return 0;
}