Gym102428F Fabricating Sculptures(DP+字首和)
Gym102428F Fabricating Sculptures(DP+字首和)
Description
Miguel Angelo is a great sculptor, widely recognized for his outdoor sculptures. In his hometown, it is very common to find one of his creations in squares and gardens. People love his sculptures, not only for their beauty, but also because they look like new even after decades.The sculptures do not degrade easily due to the material and technique developed by Miguel and his staff over the years.
To build the sculptures, he first constructs its base by stacking blocks of waterproof plaster(his secret material), forming several stacks of blocks in a straight line. He always uses identical blocks, and each stack has at least one block. To stabilize the structure, he surrounds it by two big glass panes, one behind the stacks and one in front of them. Then he waits for the rain for as long as it takes. If the structure is such that it doesn’t accumulate water during this procedure, Miguel is sure that the base can be used to obtain a piece of long-lasting artwork.Notice that water will accumulate on a block if there are obstacles (other blocks) on both sides(to the left and to the right).
The following picture shows the front view of several different bases. All of them consist of three stacks made of a total of six blocks, with each stack having at least one block as required.However, the eight bases on the left will lead to long-lasting artwork, while the two bases on the right will not.
Miguel Angelo is receiving a lot of sculpture requests. Although he has all the freedom to create the artwork, he wants to be fair and use the same number of stacks and the same number blocks in each of the sculptures. Since he doesn’t want to sell identical sculptures to different clients, he will construct a different base each time.
He worries that he won’t be able to fulfill all the requests. Help him calculate the number of different bases given the number of stacks and the number of blocks that the base must have.
Input
The input consists of a single line that contains two integers S and B (1 ≤ S ≤ B ≤ 5000)indicating respectively the number of stacks and the number of blocks that the base must have.
Output
Output a single line with an integer indicating the number of different bases that don’t accumulate water which Miguel can construct. Because this number can be very large, output the remainder of dividing it by 1e9 + 7.
Sample Input
3 6
Sample Output
8
Sample Input 2
3 7
Sample Output 2
12
題意
給 b b b個方塊來堆疊,要求底座一定 s s s個方塊,問不擺出凹槽(能儲水)的情況有幾種。
題解
設
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]為底座有i個方塊時上面還有j個方塊可以擺放。
狀態轉移方程為:
當
j
−
i
>
i
j - i > i
j−i>i時狀態轉移方程為:
dp[i][j] = s * dp[1][j - 1] + (i - 1) * dp[2][j - 2] + ... + dp[i][j - i]
當
j
−
i
<
=
i
j - i <= i
j−i<=i時狀態轉移方程為:
dp[i][j] = i * dp[1][j - 1] + (i - 1) * dp[2][j - 2] + ... + (i - j + 1) * dp[j][0]
其實從這裡可以看出,如果用這種寫法,那複雜度相當高,肯定過不了。因此需要使用字首和來簡化這個狀態轉移方程。
在蘇學長的幫助下想了很久,終於把
p
r
e
pre
pre陣列和
s
u
m
sum
sum陣列給看懂了。
s
u
m
[
j
]
sum[j]
sum[j]表示用了
j
j
j個方塊的情況個數。
而
p
r
e
pre
pre陣列就比較難以理解。它的意思我就打個比方來解釋一下。假設
i
=
=
3
i==3
i==3,那麼
p
r
e
[
j
]
pre[j]
pre[j]就是
d
p
[
3
]
[
j
]
dp[3][j]
dp[3][j]。
畫個圖解釋一下:
其餘內容均寫入程式碼中的註釋。這道題由於我水平不足實在有點難以講透徹,可以看程式碼再仔細想想。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define lowbit(x) ((x) & -(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 1e6 + 10, NN = 5e3 + 10, INF = 0x3f3f3f3f, LEN = 20;
const ll MOD = 1e9 + 7;
const ull seed = 31;
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int s, b;
int sum[NN], pre[NN];
int dp[NN][NN]; // dp[i][j]表示底座有i個方塊時上面還有j個方塊可以擺放
void init() {}
int main() {
scanf("%d%d", &s, &b);
b -= s;
for (int i = 1; i <= s; i++) {
for (int j = 0; j <= b; j++) {
pre[j] =
(pre[j] + sum[j]) %
MOD; //將當先發現的j個方塊的排列個數也就是sum[j]加入pre[j]中,省略狀態轉移方程中的重複運算
if (j == 0)
dp[i][j] = 1;
else
dp[i][j] = pre[j];
sum[i + j] = (sum[i + j] + dp[i][j]) % MOD;
}
}
printf("%d\n", dp[s][b]);
return 0;
}
相關文章
- 字首和與二維字首和
- 字首和
- (Day4)字首和&二維字首和
- 高維字首和
- 字首和&差分
- 字首和 & 差分
- 高維字首和SOSDP
- 字首和與差分
- 組合數字首和
- 二維字首和&差分
- MySQL 字串索引和字首索引MySql字串索引
- 淺記高維字首和
- 1.Prefix字首和【模板】
- 高維字首和(SOS DP)
- 字首和的基礎講解
- 1048 數字加密(字首和思想)加密
- 樹上字首和與差分
- 2020/9/30 Acwing-字首和
- 中綴轉字尾和字首
- 字首和的n個神奇操作
- 序列(dp+矩陣加速)矩陣
- 二維字首和 & 二維差分
- leetcode1546題解【字首和+貪心】LeetCode
- 幸運數(dp+矩陣加速)矩陣
- 巨大的數(dp+矩陣加速)矩陣
- 字首樹
- luoguP5369 [PKUSC2018] 最大字首和
- 高維字首和/SOS DP 學習筆記筆記
- 演算法之字首樹——最大異或和演算法
- 1588 所有奇數長度子陣列的和(字首和)陣列
- E - Remove Pairs(狀壓dp+博弈論)REMAI
- 子集列舉最佳化與高維字首和
- 二維字首和與差分、離散化技巧
- P4427 [BJOI2018]求和(LCA+字首和)
- cf1043E. Mysterious Crime(二分 字首和)
- POJ-3061 Subsequence(字首和+二分/尺取)
- Python字串字首Python字串
- HDU 5816 Hearthstone(狀態壓縮DP+概率)