当前位置:网站首页>【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;
}
边栏推荐
- RAID disk array
- sql concat()函数
- STL source code analysis: conceptual understanding of iterators, and code testing.
- B站崩了,如果是你是那晚负责的开发人员你会怎么做?
- [GO语言基础] 一.为什么我要学习Golang以及GO语言入门普及
- 首届人工智能安全大赛正式启动
- Proof of distance calculation from space vertex to plane and its source code
- 人工肌肉智能材料新突破
- mysql高阶语句(一)
- Universal js time date format conversion
猜你喜欢

阿里二面:列出 Api 接口优化的几个技巧

Playing script killing with AI: actually more involved than me

Go uses the mencached cache

架构设计指南 如何成为架构师

Go 使用 freecache 缓存

PXE efficient mass network capacity

C#的访问修饰符,声明修饰符,关键字有哪些?扫盲篇

【MySQL】MySQL中如何实现分页操作

From catching up to surpassing, domestic software shows its talents

VR机器人教你如何正确打乒乓球
随机推荐
[GO语言基础] 一.为什么我要学习Golang以及GO语言入门普及
MySQL basics [naming convention]
golang : Zap log integration
2020 ACM | MoFlow: An Invertible Flow Model for Generating Molecular Graphs
雷总个人博客看到
Ali two sides: Sentinel vs Hystrix comparison, how to choose?
“AI教练”请进家,家庭智能健身蓬勃发展
Detailed explanation of numpy multidimensional array ndarray
How to understand plucker coordinates (geometric understanding)
图解关系数据库设计思想,这也太形象了
Mobile phone side scroll to page to specify location
Electron日常学习笔记
assert
Camera coordinate system, world coordinate system, pixel coordinate system conversion, and Fov conversion of OPENGLDEFocal Length and Opengl
和AI一起玩儿剧本杀:居然比我还入戏
What are the access modifiers, declaration modifiers, and keywords in C#?Literacy articles
上传文件--文件类型大全,图片类型,文档类型,视频类型,压缩包类型
Pioneer in Distributed Systems - Leslie Lambert
The calculation of the determinant of the matrix and its source code
numpy 多维数组ndarray的详解