luogu P5289 [十二省联考2019]皮配 背包
LINK:皮配
我承认是一道很难的题目。
不过对于这道题 部分分的提示显得尤为重要。
首先是 40分的暴力dp 很容易想 但是不容易写。
从40分可以发现我们只需要把蓝阵营和鸭派系的人数给存在起来就行了 此时可以获得50分。
观察题目中存在k==0的情况 可以发现 加入阵营和派系没有什么关系 所以就可以分开的做。
考虑100分 容易发现有毒的学校就30个 对于这三十个城市单独做暴力dp 剩下的按照上述方法。
一个难点:可以发现 学校选择的派系是影响城市的 所以感觉这样做不太行。
把有毒的城放在一起dp 很遗憾这样做复杂度最快也是\(nm^2\)的 过不了。
可以发现 对于那些没有毒的学校但有毒的城市来说 没有毒的学校还是可以对于派系随便选的。
对于有毒的城市选择阵营的时候一起做 选择派系的时候单独做。
这样还是只做了k个城市。
设总体的状态为f[i][j]表示前T个城市蓝阵营i人鸭派系j的方案数。
对于每个城市单独dp的话需要提前处理一个g数组 表示当前城市 前G个学校蓝阵营i人鸭派系j人的方案数。
进一步的可以发现这个状态可以变成g1[j]表示加入蓝阵营鸭派系j人 g2[j]表示加入红阵营j人的方案数。
可以发现合并的时候还要枚举一个决策k 所以总复杂度为\(km^3\)的。
一个trick 直接让g1和g2代替f数组 然后再进行转移 这样就不需要合并背包了。
复杂度\(km^2\). 没开o2速度排在rk8 常数海星. !注意边界问题。
const int MAXN=1010,maxn=2510;
int n,T,c,C0,C1,sum,D0,D1,lim1,lim2;
int sc[MAXN],wc[MAXN],f[maxn][maxn];
struct wy{int c,s;int op;}t[MAXN];
int f1[maxn],f2[maxn],g1[maxn][maxn],g2[maxn][maxn];
inline void add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
inline int cmp(wy a,wy b){return a.c<b.c;}
inline int calc1(int s)
{
int l=max(0,sum-s-C1),r=C0-s;
if(l>r)return 0;
if(!l)return f1[r];
return (f1[r]-f1[l-1]+mod)%mod;
}
inline int calc2(int s)
{
int l=max(0,sum-s-D1),r=D0-s;
if(l>r)return 0;
if(!l)return f2[r];
return (f2[r]-f2[l-1]+mod)%mod;
}
inline void cle()
{
rep(1,n,i)sc[i]=wc[i]=0;
rep(0,max(C0,D0),i)f1[i]=f2[i]=0;
rep(0,lim1,i)rep(0,lim2,j)g1[i][j]=g2[i][j]=f[i][j]=0;
lim1=lim2=sum=0;
}
int main()
{
freopen("1.in","r",stdin);
get(T);
while(T--)
{
get(n);get(c);
get(C0);get(C1);get(D0);get(D1);
rep(1,n,i)
{
int get(x),get(y);
t[i]=(wy){x,y,0};
sum+=y;wc[x]+=y;
}
C0=min(C0,sum);C1=min(C1,sum);
D0=min(D0,sum);D1=min(D1,sum);
int get(Q);
rep(1,Q,i)
{
int get(x),get(y);
op(x)=y+1;sc[c(x)]=1;
}
f1[0]=f2[0]=1;
//f1对城市进行dp f2对学校进行dp.
rep(1,c,i)
{
if(sc[i]||!wc[i])continue;
fep(C0,wc[i],j)add(f1[j],f1[j-wc[i]]);
}
rep(1,n,i)
{
if(op(i))continue;
fep(D0,s(i),j)add(f2[j],f2[j-s(i)]);
}
//对所有有毒的城市进行dp.
//f[i][j]表示蓝阵营i人鸭派系j人的方案数.
int flag=1,sum1=0,sum2=0;//分别表示进入阵营和进入派系的人数.
sort(t+1,t+1+n,cmp);f[0][0]=1;
rep(1,c,G)
{
int st=flag;
while(c(flag)==G&&flag<=n)++flag;
int en=flag-1;
if(!sc[G])continue;
rep(0,lim1,i)rep(0,lim2,j)g2[i][j]=g1[i][j]=f[i][j];
rep(st,en,k)//只dp有毒的城市.
{
if(op(k))
{
sum2+=s(k);
lim2=min(sum2,D0);
fep(lim1,0,i)fep(lim2,0,j)
{
g1[i][j]=((j>=s(k)?g1[i][j-s(k)]*(op(k)!=1):0)+g1[i][j]*(op(k)!=2))%mod;
g2[i][j]=((j>=s(k)?g2[i][j-s(k)]*(op(k)!=3):0)+g2[i][j]*(op(k)!=4))%mod;
}
}
}
sum1+=wc[G];
lim1=min(sum1,C0);
fep(lim1,0,i)fep(lim2,0,j)f[i][j]=((i>=wc[G]?g1[i-wc[G]][j]:0)+g2[i][j])%mod;
}
rep(1,max(C0,D0),i)add(f1[i],f1[i-1]),add(f2[i],f2[i-1]);
int ans=0;
rep(0,lim1,i)
rep(0,lim2,j)
add(ans,(ll)f[i][j]*calc1(i)%mod*calc2(j)%mod);
put(ans);cle();
}
return 0;
}
luogu P5289 [十二省联考2019]皮配 背包的更多相关文章
- luogu P5289 [十二省联考2019]皮配
传送门 首先考虑一个正常的dp,设\(f_{i,j,k}\)为前\(i\)个学校,\(j\)人在\(\color{#0000FF}{蓝阵营}\),\(k\)人在\(\color{#654321}{吔} ...
- 洛谷P5289 [十二省联考2019]皮配(01背包)
啊啊啊边界判错了搞死我了QAQ 这题是一个想起来很休闲写起来很恶心的背包 对于\(k=0\)的情况,可以发现选阵营和选派系是独立的,对选城市选阵营和学校选派系分别跑一遍01背包就行了 对于\(k> ...
- 【BZOJ5498】[十二省联考2019]皮配(动态规划)
[BZOJ5498][十二省联考2019]皮配(动态规划) 题面 BZOJ 洛谷 题解 先考虑暴力\(dp\),设\(f[i][j][k]\)表示前\(i\)所学校,有\(j\)人在某个阵营,有\(k ...
- Luogu5289 十二省联考2019皮配(动态规划)
将选择导师看成先选阵营再选派系,这样有显然的O(nm2)暴力,即按城市排序后,设f[i][j][k]为前i个学校中第一个阵营有j人第一个派系有k人的方案数,暴力背包. 对于k=0,可以发现选阵营和选派 ...
- 【LuoguP5289】[十二省联考2019] 皮配
题目链接 题目描述 略 Sol 一道背包问题 首先暴力做法设 \(dp[i][j][k]\) 表示前 \(i\) 个城市的学校被分到第一阵营 \(j\) 人 第一门派 \(k\) 人的方案数. 中间一 ...
- Luogu P5285 [十二省联考2019]骗分过样例
Preface ZJOI一轮被麻将劝退的老年选手看到这题就两眼放光,省选也有乱搞题? 然后狂肝了3~4天终于打完了,期间还补了一堆姿势 由于我压缩技术比较菜,所以用的都是非打表算法,所以一共写了5K- ...
- luogu P5291 [十二省联考2019]希望
luogu loj 无论最终结果将人类历史导向何处 \(\quad\)我们选择 \(\quad\quad\)\(\large{希望}\) 诶我跟你讲,这题超修咸的 下面称离连通块内每个点距离不超过\( ...
- Luogu P5290 [十二省联考2019]春节十二响
这题是最近看到的今年省选题中最良心的一道了吧 看题+想题+写题都可以在0.5h内解决,送分含义明显啊 首先理解了题意后我们很快就能发现两个点如果要被分在一段那么必须在它们的祖先处合并 首先我们考虑下二 ...
- Luogu P5284 [十二省联考2019]字符串问题
好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...
随机推荐
- TensorFlow中的显存管理器——BFC Allocator
背景 作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 使用GPU训练时,一次训练任务无论是模型参数还是中间结果都需要占用大量显存.为了 ...
- 「单调队列优化DP」P2034 选择数字
「单调队列优化DP」P2034 选择数字 题面描述: 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入格 ...
- javaWeb7——PrepareStatement原理,Pareparedstatement和Statement的区别
查询数据返回的结果集: ResulSet: 代码实现 : PrepareStatement原理 代码实现: Pareparedstatement和Statement的区别: 注意: Statement ...
- smtp 发送邮件实例
发送邮件的关键点在于邮箱服务器地址是否一致 //smtp 服务器地址,咨询 smtp 提供商,例如 smtp.126.net 这种格式,端口和服务器地址是配套的,一般是 465 或者 25 SmtpC ...
- JVM中栈的frames详解
目录 简介 JVM中的栈 Frame Local Variables本地变量 Operand Stacks Dynamic Linking动态链接 方法执行完毕 简介 我们知道JVM运行时数据区域专门 ...
- 微信小程序热更新,小程序提示版本更新,版本迭代,强制更新,微信小程序版本迭代
相信很多人在做小程序的时候都会有迭代每当版本迭代的时候之前老版本的一些方法或者显示就不够用了这就需要用到小程序的热更新.或者说是提示升级小程序版本 editionUpdate:function(){ ...
- IOS中input键盘事件keyup 的兼容解决办法
用input监听键盘keyup事件,在安卓手机浏览器中是可以的,但是在ios手机浏览器中很慢,用输入法输入之后,并未立刻相应keyup事件. 解决办法: 在ios设备上可以用html5的input事件 ...
- day2 python六大标准数据类型简介
1.number( int , float , bool , complex ) # int 整型 intvar = 2020 print(type(intvar),id(intvar)) # f ...
- Ant-Design-Vue中关于Table组件的使用
1. 如何自定义表格列头: <a-table :columns="columns" :dataSource="dataSource"> <sp ...
- Java数组倒置
Java数组之 -- 数组倒置 方法一 : package mytest; public class test2 { public static void main(String[] args ...