当前位置:网站首页>【COCI 2020/2021 Round #2 D】Magneti(DP)
【COCI 2020/2021 Round #2 D】Magneti(DP)
2022-07-30 05:51:00 【SSL_TJH】
Magneti
题目链接:COCI 2020/2021 Round #2 D
题目大意
给你 n 个物品,每个有一个值,而且物品之间不同。
然后有一个长度为 L 的板子,然后你要把物品放在每个整点上面,使得两个物品之间的距离不小于它们权值的最大值。
然后问你有多少种方法。
思路
考虑 DP,发现不太能 DP,因为跟两个有关,但是不可以 2 n 2^n 2n。
考虑转化一下,发现如果我们确定了顺序,那最少要长度为多少的板子呢?
思考一下会发现两个之间占了 max ( a i , a i + 1 ) \max(a_i,a_{i+1}) max(ai,ai+1) 的空位,那总共要的位置就是这些的和加上 n n n。
那多出的位置我们可以用插板法来分配。
那问题就变成了求对于每个 max \max max 的和的结果,有多少种顺序对应呢?
考虑贡献的位置,也就是大的那个,于是考虑从小到大加数,那每次跟前面的多少个相邻就是贡献多少个自己。
然后考虑放进去之后会有若干块,块之间不相邻,之后再用数合并。
然后就列出一个 DP: f i , j , k , 0 / 1 / 2 , w f_{i,j,k,0/1/2,w} fi,j,k,0/1/2,w 为前 i i i 个数放进去,一边空着的 j j j 个块,两边空着的 k k k 个块,两段的块已经放了 0 / 1 / 2 0/1/2 0/1/2 个,当前 max \max max 的和为 w w w。
然后分类讨论转移。
发现会超时,因为是 O ( n 3 L ) O(n^3L) O(n3L) 的。
考虑优化,观察一下转移的式子会发现 j j j 只有在两端的时候才会加,所以 j j j 的大小其实也是 0 / 1 / 2 0/1/2 0/1/2,然后变成 O ( n 2 L ) O(n^2L) O(n2L) 就可以过了。
代码
#include<cstdio>
#include<algorithm>
#define mo 1000000007
using namespace std;
const int N = 51;
const int M = 1e4 + 10;
int n, L, a[N], jc[M], inv[M], invs[M];
int f[2][3][N][3][M], inv2;
int add(int x, int y) {
return x + y >= mo ? x + y - mo : x + y;}
int dec(int x, int y) {
return x < y ? x - y + mo : x - y;}
int mul(int x, int y) {
return 1ll * x * y % mo;}
int C(int x, int y) {
if (y < 0 || y > x) return 0; return mul(jc[x], mul(invs[y], invs[x - y]));}
int ksm(int x, int y) {
int re = 1; while (y) {
if (y & 1) re = mul(re, x); x = mul(x, x); y >>= 1;} return re;}
void Init() {
jc[0] = 1; for (int i = 1; i < M; i++) jc[i] = mul(jc[i - 1], i);
inv[0] = inv[1] = 1; for (int i = 2; i < M; i++) inv[i] = mul(inv[mo % i], mo - mo / i);
invs[0] = 1; for (int i = 1; i < M; i++) invs[i] = mul(invs[i - 1], inv[i]);
inv2 = ksm(2, mo - 2);
}
void ck(int &x, int y) {
x = add(x, y);
}
int main() {
// printf("%.3lf", (sizeof(f) * 2) / 1024.0 / 1024.0);
freopen("magnet.in", "r", stdin);
freopen("magnet.out", "w", stdout);
Init();
scanf("%d %d", &n, &L);
// for (int i = 1; i <= n; i++) a[i] = 1;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]); sort(a + 1, a + n + 1);
if (n == 1) {
printf("%d", L); return 0;
}
f[0][0][0][0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 3; j++)
for (int k = 0; k + j < i; k++)
for (int l = 0; l <= 2; l++)
for (int s = 0; s <= L; s++)
if (f[(i & 1) ^ 1][j][k][l][s]) {
int x = f[(i & 1) ^ 1][j][k][l][s]; f[(i & 1) ^ 1][j][k][l][s] = 0;
if (l < 2) {
ck(f[i & 1][j + 1][k][l + 1][s], (2 - l) * x);
if (s + a[i] <= L) {
if (j) ck(f[i & 1][j - 1][k][l + 1][s + a[i]], mul(x, j));
if (k) ck(f[i & 1][j + 1][k - 1][l + 1][s + a[i]], mul(x, k * (2 - l)));
}
}
if (s + a[i] <= L) {
if (j) ck(f[i & 1][j][k][l][s + a[i]], mul(x, j));
if (k) ck(f[i & 1][j][k][l][s + a[i]], mul(x, 2 * k));
}
if (s + a[i] + a[i] <= L) {
if (j > 1) ck(f[i & 1][j - 2][k][l][s + a[i] + a[i]], x);
if (k > 1) ck(f[i & 1][j][k - 1][l][s + a[i] + a[i]], mul(x, mul(k, k - 1)));
if (j && k) ck(f[i & 1][j][k - 1][l][s + a[i] + a[i]], mul(x, mul(j, k)));
}
ck(f[i & 1][j][k + 1][l][s], x);
}
}
int ans = 0;
for (int i = 0; i <= L; i++) {
ck(ans, mul(f[n & 1][0][0][2][i], C(L - i + n - 1, n)));
}
printf("%d", ans);
return 0;
}
边栏推荐
- C#的访问修饰符,声明修饰符,关键字有哪些?扫盲篇
- MySQL基础篇【命名规范】
- STL source code analysis: conceptual understanding of iterators, and code testing.
- Go: use gorm query record
- Redis download and installation
- The introduction of AI meta-learning into neuroscience, the medical effect is expected to improve accurately
- The calculation of the determinant of the matrix and its source code
- MySQL master-slave replication configuration construction, one step in place
- ArrayList
- Let the "label" content in Baidu map generator expand--solution
猜你喜欢

uniapp中canvas与v-if更“配”

AI元学习引入神经科学,医疗效果有望精准提升

相机坐标系,世界坐标系,像素坐标系三者转换,以及OPENGLDEFocal Length和Opengl 的 Fov转换

分布式系统中的开创者—莱斯利·兰伯特

Calculate the inverse source of the matrix (using the adjoint matrix, a 3x3 matrix)

图解关系数据库设计思想,这也太形象了

【雷达目标检测】恒定阈值法和恒虚警(CFAR)法及代码实现

Camera coordinate system, world coordinate system, pixel coordinate system conversion, and Fov conversion of OPENGLDEFocal Length and Opengl

How to understand plucker coordinates (geometric understanding)

bean的生命周期
随机推荐
From catching up to surpassing, domestic software shows its talents
入选“十大硬核科技”,详解可信密态计算(TECC)技术点
RAID disk array
The usage of window.open(), js opens a new form
阿里二面:Sentinel vs Hystrix 对比,如何选择?
Go 使用 freecache 缓存
阿里二面:列出 Api 接口优化的几个技巧
进制转换。。。
ETL为什么经常变成ELT甚至LET?
MySQL master-slave replication configuration construction, one step in place
AI can identify race from X-rays, but no one knows why
Upload file -- file type, picture type, document type, video type, compressed package type
Electron之初出茅庐——搭建环境并运行第一个程序
AI可通过X光片识别种族,但没人知道为什么
Huawei released "ten inventions", including computing, intelligent driving and other new fields
Headline 2: there are several kinds of common SQL errors in MySQL usage?
让百度地图生成器里的“标注”内容展开--解决方案
redis实现分布式锁的原理
ArrayList
go : 使用 grom 删除数据库数据