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

题面

BZOJ

洛谷

题解

先考虑暴力\(dp\),设\(f[i][j][k]\)表示前\(i\)所学校,有\(j\)人在某个阵营,有\(k\)人在某个派系的方案数。

发现如果\(k=0\),那么可以先决策每个城市选择哪一个阵营,再对于每个学校选择哪一个派系。显然两者之间不冲突,分开\(dp\)再乘起来就行了。

加入限制,每个限制的形式即在某个城市选定了某个阵营之后,这个学校只有一种选择。

先把没有限制的部分处理完,首先这些学校单独拎出来\(dp\)肯定没有问题。

不存在限制学校的城市也可以单独拎出来\(dp\)。

剩下的部分我们用前面的那个暴力\(dp\),这样子同时限制了两维就可以满足限制关系了。

最后我们枚举暴力\(dp\)的状态,利用前缀和就可以快速拼接两侧的答案。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define MOD 998244353
#define MAX 2550
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m,C0,C1,D0,D1,ans;
int fr[MAX],S[MAX],ss[MAX],sum;
int g1[MAX],g2[MAX];
vector<int> p[MAX];
int K,lim[MAX],Lim[MAX];
int f[MAX][MAX],g[MAX][MAX];
int Calc(int x,int y)
{
int lc=max(0,sum-x-C1),rc=C0-x;
int ld=max(0,sum-y-D1),rd=D0-y;
if(lc>rc||ld>rd)return 0;
return 1ll*(g2[rc]-(lc?g2[lc-1]:0)+MOD)*(g1[rd]-(ld?g1[ld-1]:0)+MOD)%MOD;
}
int main()
{
int T=read();
while(T--)
{
n=read();m=read();C0=read();C1=read();D0=read();D1=read();
for(int i=1;i<=n;++i)
{
fr[i]=read();S[i]=read();
sum+=S[i];ss[fr[i]]+=S[i];
}
K=read();
for(int i=1;i<=n;++i)lim[i]=-1;
for(int i=1;i<=m;++i)Lim[i]=-1;
for(int i=1;i<=K;++i)
{
int x=read(),q=read();
lim[x]=Lim[fr[x]]=q;
p[fr[x]].push_back(x);
}
g1[0]=g2[0]=1;
int s1=0,s2=0;
for(int i=1;i<=n;++i)
{
s1+=S[i];if(~lim[i])continue;
for(int j=min(s1,D0);j>=S[i];--j)
g1[j]=(g1[j]+g1[j-S[i]])%MOD;
}
for(int i=1;i<=m;++i)
{
s2+=ss[i];if(!ss[i]||~Lim[i])continue;
for(int j=min(s2,C0);j>=ss[i];--j)
g2[j]=(g2[j]+g2[j-ss[i]])%MOD;
}
for(int i=1;i<=D0;++i)g1[i]=(g1[i-1]+g1[i])%MOD;
for(int i=1;i<=C0;++i)g2[i]=(g2[i-1]+g2[i])%MOD;
f[0][0]=1;
for(int i=1,sc=0,sd=0;i<=m;++i)
{
if(!~Lim[i]||!ss[i])continue;
for(int j=0;j<=C0&&j<=sc;++j)
for(int k=0;k<=D0&&k<=sd;++k)g[j][k]=f[j][k];
for(int qwq=0;qwq<(int)p[i].size();++qwq)
{
int x=p[i][qwq];sd+=S[x];
int t0=lim[x]!=0,t1=lim[x]!=1,t2=lim[x]!=2,t3=lim[x]!=3;
for(int j=min(C0,sc);~j;--j)
for(int k=min(D0,sd);~k;--k)
if(k>=S[x])
{
f[j][k]=(f[j][k]*t1+f[j][k-S[x]]*t0)%MOD;
g[j][k]=(g[j][k]*t3+g[j][k-S[x]]*t2)%MOD;
}
else f[j][k]=f[j][k]*t1,g[j][k]=g[j][k]*t3;
}
sc+=ss[i];
for(int j=min(C0,sc);~j;--j)
for(int k=min(D0,sd);~k;--k)
if(j>=ss[i])f[j][k]=(f[j-ss[i]][k]+g[j][k])%MOD;
else f[j][k]=g[j][k];
}
for(int i=0;i<=C0;++i)
for(int j=0;j<=D0;++j)
if(f[i][j])ans=(ans+1ll*f[i][j]*Calc(i,j))%MOD;
printf("%d\n",ans);
sum=ans=0;
for(int i=0;i<=D0;++i)g1[i]=0;
for(int i=0;i<=C0;++i)g2[i]=0;
for(int i=1;i<=n;++i)fr[i]=S[i]=0,lim[i]=0;
for(int i=1;i<=m;++i)p[i].clear(),ss[i]=0,Lim[i]=0;
for(int i=0;i<=C0;++i)for(int j=0;j<=D0;++j)g[i][j]=f[i][j]=0;
}
return 0;
}

【BZOJ5498】[十二省联考2019]皮配(动态规划)的更多相关文章

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

    LINK:皮配 我承认是一道很难的题目. 不过对于这道题 部分分的提示显得尤为重要. 首先是 40分的暴力dp 很容易想 但是不容易写. 从40分可以发现我们只需要把蓝阵营和鸭派系的人数给存在起来就行 ...

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

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

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

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

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

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

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

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

  6. 【LOJ】#3051. 「十二省联考 2019」皮配

    LOJ#3051. 「十二省联考 2019」皮配 当时我在考场上觉得这题很不可做... 当然,出了考场后再做,我还是没发现学校和城市是可以分开的,导致我还是不会 事实上,若一个城市投靠了某个阵营,学校 ...

  7. [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增

    题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...

  8. [十二省联考2019]异或粽子——可持久化trie树+堆

    题目链接: [十二省联考2019]异或粽子 求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间. 为了快速得到一个区间的异或和,将原序列做前缀异或和. 对于每个点作为右端点时,我们维护出 ...

  9. 【BZOJ5495】[十二省联考2019]异或粽子(主席树,贪心)

    [BZOJ5495][十二省联考2019]异或粽子(主席树,贪心) 题面 BZOJ 洛谷 题解 这不是送分题吗... 转异或前缀和,构建可持久化\(Trie\). 然后拿一个堆维护每次的最大值,每次如 ...

随机推荐

  1. Skywalking部署常见问题以及注意事项

    Skywalking部署常见问题以及注意事项 Intro SkyWalking 创建与2015年,提供分布式追踪功能.从5.x开始,项目进化为一个完成功能的Application Performanc ...

  2. 在java中写出完美的单例模式

    1. 前言 单例(Singleton)应该是开发者们最熟悉的设计模式了,并且好像也是最容易实现的——基本上每个开发者都能够随手写出——但是,真的是这样吗? 作为一个Java开发者,也许你觉得自己对单例 ...

  3. Vue2.5笔记:Vue的实例与生命周期

    理解与认识 Vue 的实例是我们学习 Vue 非常重要的一步,也是非常必须的,因为实例是它的一个起点,也是它的一个入口,只有我们创建一个 Vue 实例之后,我们才行利用它进行一些列的操作. 首先 Vu ...

  4. ASP.NET Zero--开发指南

    ASP.NET Zero--开发指南(Lyhcee 译) 01. 前期介绍 02. 前期要求 03. 解决方案结构(层) 04. 前端应用程序 05. 后端应用程序 06.WEB.HOST应用程序 0 ...

  5. python调用C程序代码

    DHT11的驱动使用C语言编写   然后用python调用C的程序 显示温湿度 pycall.py文件如下: #!/usr/bin/env python # -*- coding:utf-8 -*- ...

  6. (转)聊聊Greenplum的那些事

    开卷有益——作者的话 有时候真的感叹人生岁月匆匆,特别是当一个IT人沉浸于某个技术领域十来年后,蓦然回首,总有说不出的万千感慨. 笔者有幸从04年就开始从事大规模数据计算的相关工作,08年作为Gree ...

  7. 如何设置Oracle数据库客户端字符集以及系统中的NLS_LANG环境变量

    概述: 本地化是系统或软件运行的语言和文化环境.设置NLS_LANG环境参数是规定Oracle数据库软件本地化行为最简单的方式. NLS_LANG参数不但指定了客户端应用程序和Oracle数据库所使用 ...

  8. Pycharm 消除波浪线

    转载:https://blog.csdn.net/youyouran12314/article/details/77719261 Pycharm环境下显示 在代码中显示许多波浪线,查看详情显示Spel ...

  9. ABAP 7.53 中的ABAP SQL(原Open SQL)新特性

    S/4 HANA 1809 已经在上月发布,随之而来的是ABAP 7.53. 本文是更新文档中ABAP SQL的部分的翻译. 本次更新的内容较多,主要内容包括:Open SQL更名为ABAP SQL: ...

  10. Git命令行管理代码、安装及使用

    出处:https://www.cnblogs.com/ximiaomiao/p/7140456.html Git安装和使用     目的:通过Git管理github托管项目代码 一.下载安装Git 1 ...