Topcoder 15405 - PrettyLiar(可删除背包+前缀和优化 dp)
题意:
给出两个长度为 \(n\) 的数组 \(a,b\) 和一个整数 \(s\)。
你可以任意重排数组 \(a,b\),总共 \((n!)^2\) 种方案。
现在又两个人 A,B 来玩游戏,两人轮流操作,A 先操作。
每次操作当前选手会取出各自数组的第一个元素 \(x\) 并将它删去,并令 \(s\) 减去 \(x\),如果发现 \(s\leq 0\),那么当前操作的人输,游戏结束。
求在所有 \((n!)^2\) 的方案中,有多少种能够使得 A 赢,答案模 \(10^9+7\)。
\(1 \leq n,a_i,b_i \leq 100\),\(1 \leq s \leq \sum(a_i+b_i)\),时限 \(=4s\)。
我竟然现场 40min 就 A 了这道题,incredible!
拿总方案数 \(-\) B 赢的方案数。
考虑 B 赢是什么情况。肯定我们删到了某个位置 \(i\),然后删除完第 \(i\) 个位置上的数之后 \(s \leq 0\),然后 A 就输了。
假设 A 在第 \(i\) 次删除的数为 \(x\)。那么在删除 \(x\) 之前,删除的所有数之和 \(<s\),而删完 \(x\) 之后删除的所有数之和 \(\geq s\)。
我们枚举这个 \(i\) 和 \(x\),假设删 \(a_i\) 之前删除的所有数之和为 \(sum\),那么我们可以得到不等式 \(s-x \leq sum \lt s\)。
那么题目转化为:你在 \(a_j\) 中选择 \(i-1\) 个数填在 \(a_1,a_2,\dots,a_{i-1}\) 的位置(已经放好的 \(x\) 就不能再被选择了),再从 \(b_j\) 中选择 \(i-1\) 个数放在 \(b_1,b_2,\dots,b_{i-1}\) 的位置,满足 \(a,b\) 数组中选出来的 \(2(i-1)\) 个数之和在 \([s-x,s)\) 之间,求方案数。
首先 \(n^3\) 的暴力 \(dp\) 是很显然的。你每枚举一个 \(x\),就相当于从 \(a\) 数组中踢掉了一个数,就重新做一遍背包,\(dpa_{i,j,k}\) 表示在 \(a_1,a_2,\dots,a_i\) 中选择 \(j\) 个数和为 \(k\) 的方案数。\(dpb\) 同理。然后枚举 \(sum\) 和选出来的 \(i-1\) 个 \(a_i\) 的和,用乘法原理计算贡献。\(a_1,a_2,\dots,a_{i-1}\) 可以随便排,方案数 \((i-1)!\),\(b_1,b_2,\dots,b_{i-1}\) 也可以随便排,方案数也是 \((i-1)!\)。\(a_{i+1},a_{i+2},\dots,a_{n}\),\(b_i,b_{i+1},\dots,b_n\) 也依次有一个全排列的系数,所以总的乘法系数是 \(((i-1)!)^2\times(n-i)!\times(n-i+1)!\)。总复杂度 \(n^5\)
不过借鉴 [CTSC2012] 假面 的经验,可以先预处理出整个序列的 \(dpa\),然后对每个 \(x\) 都跑一遍可删除背包。正推的方程式是 \(dp_{i,j,k}=dp_{i-1,j,k}+dp_{i-1,j-1,k-x}\)。现在是在已知 \(dp_{i}\) 的情况下求出 \(dp_{i-1}\)。注意到 \(dp_{i-1,0,k}=dp_{i,0,k}\),所以我们可以先还原出 \(dp_{i-1,0,k}\),再根据 \(dp_{i-1,1,k}=dp_{i,1,k}-dp_{i-1,0,k-x}\) 还原出 \(dp_{i-1,1,k}\),以此类推,还原的复杂度是 \(n^2\) 的。
接下来是计算答案,还是枚举 \(a\) 贡献的和 \(suma\),不过注意到 \(sum\) 的取值范围是一段区间,所有 \(b\) 贡献的和的范围也是个区间 \([s-x-suma,s-suma)\),前缀和转移,又可以优化掉一个 \(n\)。
时间复杂度 \(\mathcal O(n^4)\)
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
typedef long long ll;
typedef pair<int,int> pii;
const int MOD=1e9+7;
const int MAXN=100+5;
const int MAXS=2e4+5;
int n,s,a[MAXN],b[MAXN];
int dpa[MAXN][MAXS],dpb[MAXN][MAXS],sdp[MAXN][MAXS];
int ndp[MAXN][MAXS];
int fac[MAXN];
int solve(){
int sa=0,sb=0,ss=0;
fac[0]=1;for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD;
for(int i=1;i<=n;i++) sa+=a[i];
for(int i=1;i<=n;i++) sb+=b[i];
ss=sa+sb;dpa[0][0]=1;
for(int i=1;i<=n;i++) for(int j=i;~j;j--) for(int k=sa;~k;k--)
if(j>=1&&k>=a[i]) dpa[j][k]=(dpa[j][k]+dpa[j-1][k-a[i]])%MOD;
dpb[0][0]=1;
for(int i=1;i<=n;i++) for(int j=i;~j;j--) for(int k=sb;~k;k--)
if(j>=1&&k>=b[i]) dpb[j][k]=(dpb[j][k]+dpb[j-1][k-b[i]])%MOD;
for(int i=0;i<=n;i++){
sdp[i][0]=dpb[i][0];
for(int j=1;j<=ss;j++) sdp[i][j]=(sdp[i][j-1]+dpb[i][j])%MOD;
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=n;j++) for(int k=0;k<=sa;k++) ndp[j][k]=dpa[j][k];
for(int j=0;j<n;j++) for(int k=0;k<=sa-a[i];k++){
ndp[j+1][k+a[i]]=(ndp[j+1][k+a[i]]-ndp[j][k]+MOD)%MOD;
}
int l=max(s-a[i],0),r=s-1;
for(int j=0;j<n;j++){
int sum=0;
for(int k=0;k<=sa;k++){
if(k>r) break;
int nl=l-k,nr=r-k;
sum=(sum+1ll*ndp[j][k]*sdp[j][nr]%MOD)%MOD;
if(nl>0) sum=(sum-1ll*ndp[j][k]*sdp[j][nl-1]%MOD+MOD)%MOD;
}
ans=(ans+1ll*sum*fac[j]%MOD*fac[j]%MOD*fac[n-j-1]%MOD*fac[n-j]%MOD)%MOD;
}
}
int tot=1ll*fac[n]*fac[n]%MOD;
return (tot-ans+MOD)%MOD;
}
class PrettyLiar{
public:
int count(int S,vector<int> kaede,vector<int> kanade){
s=S;n=kaede.size();
for(int i=0;i<n;i++) a[i+1]=kaede[i],b[i+1]=kanade[i];
return solve();
}
};
//PrettyLiar pro;
Topcoder 15405 - PrettyLiar(可删除背包+前缀和优化 dp)的更多相关文章
- LOJ 6089 小Y的背包计数问题 —— 前缀和优化DP
题目:https://loj.ac/problem/6089 对于 i <= √n ,设 f[i][j] 表示前 i 种,体积为 j 的方案数,那么 f[i][j] = ∑(1 <= k ...
- P5241 序列(滚动数组+前缀和优化dp)
P5241 序列 挺神仙的一题 看看除了dp好像没什么其他办法了 想着怎么构个具体的图出来,然鹅不太现实. 于是我们想办法用几个参数来表示dp数组 加了几条边肯定要的吧,于是加个参数$i$表示已加了$ ...
- CDOJ 1307 ABCDE 前缀和优化dp
ABCDE 题目连接: http://acm.uestc.edu.cn/#/problem/show/1307 Description Binary-coded decimal (BCD) is a ...
- bzoj 1044 [HAOI2008]木棍分割——前缀和优化dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1044 前缀和优化. 但开成long long会T.(仔细一看不用开long long) #i ...
- bzoj 3398 [Usaco2009 Feb]Bullcow 牡牛和牝牛——前缀和优化dp / 排列组合
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3398 好简单呀.而且是自己想出来的. dp[ i ]表示最后一个牡牛在 i 的方案数. 当前 ...
- bzoj2431: [HAOI2009]逆序对数列(前缀和优化dp)
2431: [HAOI2009]逆序对数列 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 2312 Solved: 1330[Submit][Stat ...
- CF601C Kleofáš and the n-thlon(期望+前缀和优化dp)
传送门 解题思路 要求这个人的排名,我们可以先求出某个人比他排名靠前的概率,然后再乘上\(m-1\)即为答案.求某个人比他排名靠前可以用\(dp\),设\(f[i][j]\)表示前\(i\)场比赛某人 ...
- 2018.09.25 51nod1597 有限背包计数问题(背包+前缀和优化)
传送门 dp好题. 我认为原题的描述已经很清楚了: 你有一个大小为n的背包,你有n种物品,第i种物品的大小为i,且有i个,求装满这个背包的方案数有多少. 两种方案不同当且仅当存在至少一个数i满足第i种 ...
- Codeforces Round #274 (Div. 1) C. Riding in a Lift 前缀和优化dp
C. Riding in a Lift Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/480/pr ...
随机推荐
- 【数据结构与算法Python版学习笔记】树——相关术语、定义、实现方法
概念 一种基本的"非线性"数据结构--树 根 枝 叶 广泛应用于计算机科学的多个领域 操作系统 图形学 数据库 计算机网络 特征 第一个属性是层次性,即树是按层级构建的,越笼统就越 ...
- vue3.x非兼容的变更
走马观花似的看看从vue2.x开始到vue3.x的一些非兼容性的变更,这样在将来升级过程中遇到那些奇奇怪怪的不能用的时候,就会很容易解决啦. 全局 API 全局 Vue API 已更改为使用应用程序实 ...
- 封装ARX给.Net调用
1:创建工程名.def的文件,内容如下: 2:def文件位置: 3:属性页配置: 4:acrxEntryPoint.cpp下面添加如下代码(可以传参数) 5:c#调用 怕自己忘记,记录一下.
- beta事后分析
设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 软件要解决的问题是是开发一个简易方便,为用户带来便捷且功能齐全的表情包管理小程序: 预期的典型用户 ...
- [no_code][Beta]发布声明报告
$( "#cnblogs_post_body" ).catalog() 软件下载 一个全新的超简易的OCR表单识别工具 轻松拍照,实现手写表格识别 一键打开,支持多种应用打开你的表 ...
- [Beta]the Agiles Scrum Meeting 5
会议时间:2020.5.19 20:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 issue yjy 为评测机增加更多评测指标 评测部分增加更多评测指标 tq 为评测机增加更多评测指标 ...
- Noip模拟50 2021.9.10
已经好长时间没有考试不挂分的良好体验了... T1 第零题 开场数据结构,真爽 对于这道题首先要理解对于一条链从上向下和从下向上走复活次数相等 (这可能需要晚上躺在被窝里面脑摸几种情况的样例) 然后就 ...
- qgis3.16.6+vs2017再编译(debug+release)
参考 https://www.cnblogs.com/superbi/p/11188145.html 文章以及其它文章,对qggis3.16.6进行了重新编译 一.编译准备 1.Cygwin 1.1安 ...
- 21.6.29 test
\(NOI\) 模拟赛 \(T1\) 正解是个题解难以理解的数论,结果是组合数相加.暴力分拿满了,尝试打了 \(20*20\) 的表,最后大概打出了个三角形的表,并且帮我找到了一些性质.\(45\)p ...
- 【数据结构&算法】05-线性表之数组
目录 前言 线性结构与非线性结构 数组 数组的两个限制 数组的随机访问特性 数组的操作 插入操作 删除操作 数组越界 容器 数组下标 前言 本笔记主要记录数组的一些基础特性及操作. 顺便解答下为什么大 ...