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]皮配 背包的更多相关文章

  1. luogu P5289 [十二省联考2019]皮配

    传送门 首先考虑一个正常的dp,设\(f_{i,j,k}\)为前\(i\)个学校,\(j\)人在\(\color{#0000FF}{蓝阵营}\),\(k\)人在\(\color{#654321}{吔} ...

  2. 洛谷P5289 [十二省联考2019]皮配(01背包)

    啊啊啊边界判错了搞死我了QAQ 这题是一个想起来很休闲写起来很恶心的背包 对于\(k=0\)的情况,可以发现选阵营和选派系是独立的,对选城市选阵营和学校选派系分别跑一遍01背包就行了 对于\(k> ...

  3. 【BZOJ5498】[十二省联考2019]皮配(动态规划)

    [BZOJ5498][十二省联考2019]皮配(动态规划) 题面 BZOJ 洛谷 题解 先考虑暴力\(dp\),设\(f[i][j][k]\)表示前\(i\)所学校,有\(j\)人在某个阵营,有\(k ...

  4. Luogu5289 十二省联考2019皮配(动态规划)

    将选择导师看成先选阵营再选派系,这样有显然的O(nm2)暴力,即按城市排序后,设f[i][j][k]为前i个学校中第一个阵营有j人第一个派系有k人的方案数,暴力背包. 对于k=0,可以发现选阵营和选派 ...

  5. 【LuoguP5289】[十二省联考2019] 皮配

    题目链接 题目描述 略 Sol 一道背包问题 首先暴力做法设 \(dp[i][j][k]\) 表示前 \(i\) 个城市的学校被分到第一阵营 \(j\) 人 第一门派 \(k\) 人的方案数. 中间一 ...

  6. Luogu P5285 [十二省联考2019]骗分过样例

    Preface ZJOI一轮被麻将劝退的老年选手看到这题就两眼放光,省选也有乱搞题? 然后狂肝了3~4天终于打完了,期间还补了一堆姿势 由于我压缩技术比较菜,所以用的都是非打表算法,所以一共写了5K- ...

  7. luogu P5291 [十二省联考2019]希望

    luogu loj 无论最终结果将人类历史导向何处 \(\quad\)我们选择 \(\quad\quad\)\(\large{希望}\) 诶我跟你讲,这题超修咸的 下面称离连通块内每个点距离不超过\( ...

  8. Luogu P5290 [十二省联考2019]春节十二响

    这题是最近看到的今年省选题中最良心的一道了吧 看题+想题+写题都可以在0.5h内解决,送分含义明显啊 首先理解了题意后我们很快就能发现两个点如果要被分在一段那么必须在它们的祖先处合并 首先我们考虑下二 ...

  9. Luogu P5284 [十二省联考2019]字符串问题

    好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...

随机推荐

  1. Java桌面应用程序打包

    IDEA环境生成Jar 设置配置 File -> Project Structure -> Artifacts -> + -> JAR -> From modules w ...

  2. MySQL常规操作

    数据库的相关概念 一.数据库的好处 1.可以持久化数据到本地 2.结构化查询 二.数据库的常见概念 ★ 1.DB:数据库,存储数据的容器 2.DBMS:数据库管理系统,又称为数据库软件或数据库产品,用 ...

  3. Flask路由中使用正则表达式匹配

    1.说明 由于flask并不支持直接使用正则表达式来匹配路由,我们可以使用werkzeug.routing的BaseConverter来实现 2.代码 from flask import Flask ...

  4. [JAVA]多线程之实现Callable接口

    通过继承Callable方式实现的多线程可以获取线程执行后的返回值 示例代码如下: public class Counter implements Callable<Integer> { ...

  5. day19 生成器+函数递归

    目录 一.yield表达式 1 yield表达式基本用法 二.三元表达式 三.生成式 1 列表生成式 2 字典生成式 3 集合生成式 4 生成器表达式 四.函数的递归 1 递归的定义 2 详解递归 前 ...

  6. NW.js Mac App 签名公证流程

    使用 Developer ID 为 Mac 软件签名 - Apple Developer 在MacOS 10.15之前,应用如果没有签名(signature),那么首次打开时就会弹出"无法验 ...

  7. Java String:字符串常量池(转)

    作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么? 字符串常量池的设计思想是什么? 字符串常量池在哪里? 如何操作字符串常量 ...

  8. Java中的堆和栈以及堆栈的区别

    在正式内容开始之前要说明一点,我们经常所说的堆栈堆栈是堆和栈统称,堆是堆,栈是栈,合在一起统称堆栈: 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Jav ...

  9. java 面向对象(二十四):interface:接口

    interface:接口1.使用说明: 1.接口使用interface来定义 * 2.Java中,接口和类是并列的两个结构 * 3.如何定义接口:定义接口中的成员 * * 3.1 JDK7及以前:只能 ...

  10. 数据可视化实例(十七):包点图 (matplotlib,pandas)

    排序 (Ranking) 包点图 (Dot Plot) 包点图表传达了项目的排名顺序,并且由于它沿水平轴对齐,因此您可以更容易地看到点彼此之间的距离. https://datawhalechina.g ...