100+100+50=250。最后那道期望题需要用另外的方式统计。

精灵加护

ljss 被 M 个敌人打倒在地上啦!每个敌人有一个威力值 bi。但是他手中还拥有 N 把武器!每把武器有一个威力值 ai,每个武器可以消灭威力值小于等于自己的敌人,然后就不能再用了….

但是他又发现:拿着 N 个武器好像还是打不过这些敌人!但是他不虚,因为每把武器有一个精灵附体来保护他,每个精灵可以令这把武器无视一个特定敌人的威力值而直接秒杀他!

但是他还是不太确定在精灵的帮助下能否消灭所有敌人。如果能消灭所有敌人输出“Success”,否则输出“Fail”。

对于 100%的数据,N,M<=20000

题解

如果没有那个 c,显然应该贪心。把 n 个武器从小到大排序,对于每个武器贪心选取小于等于它的最大的敌人。这样做的最优性可以用决策包容来证明。

多了那个 c,分为两种情况。

  1. 消灭的敌人小于等于自己。这种情况下 c 无用。
  2. 消灭的敌人大于自己。那么显然应该直接选择它。这样做的最优性也可以用决策包容性证明。

    注意多对一的情况。我们需要从小到大考虑所有的 c。

时间复杂度\(O(n \log n)\)。

co int N=20000+10;
struct node{int v,c;}a[N];
il bool operator<(co node&a,co node&b){
return a.v<b.v;
}
int b[N],ta[N];
bool vis[N];
multiset<int> s;
multiset<int>::iterator it;
void real_main(){
int n=read<int>(),m=read<int>();
for(int i=1;i<=n;++i) read(a[i].v);
for(int i=1;i<=m;++i) read(b[i]),vis[i]=0;
for(int i=1;i<=n;++i) read(a[i].c);
sort(a+1,a+n+1);
int tot=0;
for(int i=1;i<=n;++i){
if(!vis[a[i].c]&&b[a[i].c]>a[i].v) vis[a[i].c]=1;
else ta[++tot]=a[i].v;
}
s.clear(),s.insert(-1);
for(int i=1;i<=m;++i)
if(!vis[i]) s.insert(b[i]);
for(int i=1;s.size()>1&&i<=tot;++i){
it=s.upper_bound(ta[i]),--it;
if(*it!=-1) s.erase(it);
}
puts(s.size()==1?"Success":"Fail");
}
int main(){
freopen("guard.in","r",stdin),freopen("guard.out","w",stdout);
for(int T=read<int>();T--;) real_main();
return 0;
}

黄学长写的网络流。可以实现前缀连边。具体而言,可以将敌人从小到大排序,每个敌人向前一个连一条容量为无穷大的边。这样跑匹配即可得到60分。

相位幻击

首先 wzh1 施法造阵,造出了一个 n 个节点的树(以 1 为根),每个点上有一个点权。

但是敌人有时会干扰 wzh1,令他阵法树中某个结点的子树的所有权值都按位异或上一个值来打乱 wzh1 的部署,wzh1 偶尔也会让 ljss 随意指出两个点,然后把这条路径上的权值按位异或起来给敌人一个打击。请求出敌人每次受到的打击的值。

对于 100%的数据,n,m<=200000

题解

树剖模板题?反正我这么写就过了。实际上有一个 log 的做法。

设 z 为 x,y 的 LCA,从 x 到 y 的路径异或和=F(x)F(y)F(z)^F(fa[z]),其中 f(x)为 x 到根的异或和

然后考虑如何维护 F,考虑修改子树时的特点,所有奇数层的点的 F 值相当于异或了 x,而偶数层的点的 F 值没有变化,这是一个可以利用的特点

我们可以回想树链剖分的过程实际上是把树转化成区间,方便对子树和链进行操作,那么我们可以用类似的方法把奇数层和偶数层分开,然后把一个子树内的点并在一起,这样跨层异或就变成了区间异或

具体操作方法可以对树进行两次 DFS,第一次把奇数深度的推进数组,第二次推偶数深度的,然后记下每个点所对应的区间就可以了

也可以像刘老爷那样对于奇偶层分别打标记。

抗拒黄泉

焱犇画出了一个 n*m 的棋盘,其中有些格子是 0,有些是 1,每天 ljss 可以选择一个标有 1 的格子并标记它。只要棋盘的每行、每列都至少有一个被标记的格子时,ljss 就可以立即复活。但是 ljss 实在是太呆了,他每次只会从所有的标有 1 的格子中完全随机选择一个来标记..但是他还是想知道自己复活的期望天数。

对于 50%的数据,n,m<=8

对于 100%的数据,n,m<=20,n*m<=200,aij∈{0,1}

题解

首先说那个50分。将原图看成二分图,对行列覆盖情况进行状态压缩,暴力转移即可。

co int N=8,S=1<<8;
struct edge {int u,v;}e[N*N];
int tot; bool vis[S][S];
double f[S][S];
double dp(int s,int t){
if(vis[s][t]) return f[s][t];
vis[s][t]=1;
int same=0;
for(int i=0;i<tot;++i){
int ns=s|1<<e[i].u,nt=t|1<<e[i].v;
if(ns==s&&nt==t) ++same;
else f[s][t]+=dp(ns,nt);
}
f[s][t]/=tot-same;
f[s][t]+=(double)tot/(tot-same);
return f[s][t];
}
int main(){
freopen("refuse.in","r",stdin),freopen("refuse.out","w",stdout);
int n=read<int>(),m=read<int>();
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)if(read<int>())
e[tot++]=(edge){i,j};
vis[(1<<n)-1][(1<<m)-1]=1;
printf("%.5lf\n",dp(0,0));
return 0;
}

记 \(P(i)\) 为选 \(i\) 次才成功的概率,那么

\[ans=\sum_{i=1}^\infty i P(i)
\]

\(P(i)\) 可以通过枚举遗漏的行列来进行计算,注意这里要使用容斥原理。记 \(S\) 为一个行和列构成的集合,\(P(S)\) 为选中 \(S\) 集合内的格子的概率,那么

\[P(i)=\sum_{|S|\bmod 2=1}(1-P(S))^{i-1}P(S)-\sum_{|S|\bmod 2=0} (1-P(S))^{i-1}P(S)
\]

带入 \(ans\) 求和式

\[ans=\sum_{i=1}^\infty i \left(\sum_{|S|\bmod 2=1}(1-P(S))^{i-1}P(S)-\sum_{|S|\bmod 2=0} (1-P(S))^{i-1}P(S)\right)\\
=\sum_{|S|\bmod 2=1}\sum_{i=1}^\infty i (1-P(S))^{i-1}P(S)-\sum_{|S|\bmod 2=0}\sum_{i=1}^\infty i(1-P(S))^{i-1}P(S)
\]

前后两个第二重求和式里面的都是几何分布的期望。其实用等差*等比数列求和方式算一下就行了。

\[ans=\sum_{|S|\bmod 2=1} \frac{1}{P(S)}-\sum_{|S|\bmod 2=0}\frac{1}{P(S)}
\]

我们设格子的总数为 \(tot\),\(\pi(S)\) 为 \(S\) 集合内方块的个数,那么

\[ans=\sum_{|S|\bmod 2=1} \frac{tot}{\pi(S)}-\sum_{|S|\bmod 2=0}\frac{tot}{\pi(S)}
\]

我们不能直接枚举 \(S\),所以这里应该变动枚举量。我们直接枚举 \(\pi(S)\) 的取值。设 \(num(\pi)\) 表示 \(\pi(S)=\pi\) 的 \(S\) 的个数,注意这里的 \(num\) 是进行容斥过后的结果,即如果 \(|S|\) 为偶数,在 \(num\) 里它的贡献是负的。

\[ans=\sum_{\pi=1}^{tot}num(\pi)\frac{tot}{\pi}
\]

然后问题就转化成了求 \(num\)。

假如不选行的话,列是两两无关的。这个可以通过背包 DP 解决。由于 \(n\times m \leq 200\),所以 $\min(n,m) \leq 14 $。我们可以通过转置使得行数 \(n \leq 14\)。然后我们可以二进制枚举选了哪些行,对列剩下的部分 DP。

设已经选了 \(a\) 行,里面有 \(b\) 个格子。设 \(f(i,j,k)\) 表示前 \(i\) 列选了 \(j\) 列,里面有 \(k\) 个格子的方案数。注意这里的 \(f\) 没有经过容斥。那么

\[ans=\sum_{a,b}\sum_{j,k}f(m,j,k)\frac{tot}{k+b}(-1)^{j+a+1}
\]

而 \(f\) 的转移是普及组内容,所以问题就解决了。

时间复杂度 \(O(2^n m\cdot nm)\),算出来是 4e7。

co int N=20;
int a[N][N],sum[N];
int p[N],f[N][N*N+1]; void rotate(int&n,int&m){
static int b[N][N];
for(int i=0;i<n;++i)
for(int j=0;j<m;++j) b[j][i]=a[i][j];
swap(n,m);
for(int i=0;i<n;++i)
for(int j=0;j<m;++j) a[i][j]=b[i][j];
}
int main(){
freopen("refuse.in","r",stdin),freopen("refuse.out","w",stdout);
int n=read<int>(),m=read<int>();
int tot=0;
for(int i=0;i<n;++i)
for(int j=0;j<m;++j) tot+=read(a[i][j]);
if(n>m) rotate(n,m);
for(int i=0;i<n;++i)
for(int j=0;j<m;++j) sum[i]+=a[i][j];
double ans=0;
for(int s=0;s<1<<n;++s){
int low=0,row=0;
for(int i=0;i<n;++i)
if(s>>i&1) low+=sum[i],++row;
for(int i=0;i<m;++i){
p[i]=0;
for(int j=0;j<n;++j)
if(~s>>j&1) p[i]+=a[j][i];
}
fill(f[0],f[0]+tot+1,0);
if(row&1) f[0][low]=1,f[0][low+p[0]]+=-1;
else f[0][low]=-1,f[0][low+p[0]]+=1;
for(int i=1;i<m;++i)
for(int j=0;j<=tot;++j){
f[i][j]=f[i-1][j];
if(j>=p[i]) f[i][j]-=f[i-1][j-p[i]]; // choose
}
for(int j=1;j<=tot;++j)
ans+=(double)f[m-1][j]*tot/j;
}
printf("%.5lf\n",ans);
return 0;
}

这份代码的背包 DP 稍微有些奇怪,不过还是可以理解的。

test20190827 NOIP2019 模拟赛的更多相关文章

  1. test20190826 NOIP2019 模拟赛

    100+100+40=240.我觉得如果没做过第三题考场上却能想出来的都是神仙. 基因突变 [问题描述] 邪恶的 707 刚刚从白垩纪穿越回来,心中产生了一个念头:我要统治人类! 但是统治人类是很庞大 ...

  2. test20190818 NOIP2019 模拟赛

    0+0+20=20,不给大样例,小数据又水,还没有题解的垃圾题. A 题 问题描述: long long ago, Lxhgww 统治的国家里有 n 个城市,其中某一个城市是 capital (首都) ...

  3. test20190816 NOIP2019 模拟赛

    100+100+20=220,T3吐槽:整个考室没有一个人正确地理解了题意. 树上路径(phantasm) Akari 的学校的校门前生长着一排 n 棵树,从西向东依次编号为 1 ∼ n.相邻两棵树间 ...

  4. 题解 noip2019模拟赛Day1T3

    题面 运河计划 问题描述 水运在人类的交通运输史中一直扮演着重要的角色.借助河流.的便利,人们得以把大量的货物输送到天南海北不仅仅是自然界现成的河流,人工开凿的运河(如苏伊士运河.巴拿马运河.我国的京 ...

  5. [NOIP2019模拟赛]LuoguP4261白金元首与克劳德斯

    题目描述 给出坐标系中n个矩形,类型1的矩形每单位时间向x轴正方向移动1个单位,类型2的矩形向y轴正方向,初始矩形不重叠,一个点被矩形覆盖当且仅当它在矩形内部(不含边界),求$(-\infty ,+\ ...

  6. [NOIP2019模拟赛][AT2381] Nuske vs Phantom Thnook

    题目链接 评测姬好快啊(港记号?)暴力40pts变成60pts 因为题目说了保证蓝色点两两之间只有一条路径,所以肯定组成了一棵树,而对于每次询问的x1,y1,x2,y2的子矩阵中就存在着一个森林 不难 ...

  7. [NOIP2019模拟赛]HC1147 时空阵

    题目描述: 幽香这几天学习了魔法,准备建造一个大型的时空传送阵. 幽香现在可以在幻想乡的n个地点建造一些传送门,如果她建造了从地点a与地点b之间的传送门,那么从a到b和从b到a都只需要单位1的时间. ...

  8. [NOIP2019模拟赛]数数(gcd)

    题目大意: 求l~r中有多少数与x互质,带单点修改 分析: 两个30的部分分很好打: ·n<=1000暴力O(nq)就好了 ·$a_i<=100$用树状数组维护每个x的前缀和就好了 100 ...

  9. [NOIP2019模拟赛]序列(Sequence)

    题目大意 有一个序列$A_i$ • 对于 i ≥ 1,如果有$ A_i > 0.A_{i+1}> 0$ 且存在 $A_{i+2}$,那么法老可以令$ Ai$ 和 $A_{i+1}$ 减一, ...

随机推荐

  1. Linux交换分区内存优化

    swappiness的值的大小对如何使用swap分区是有着很大的联系的.swappiness=0的时候表示最大限度使用物理内存,然后才是 swap空间,swappiness=100的时候表示积极的使用 ...

  2. QT -- QString处理

    1. 去掉字符串多余的空格,回车等. QString QString::simplified () const Returns a string that has whitespace removed ...

  3. C#中数组、集合(ArrayList)、泛型集合List<T>、字典(dictionary<TKey,TValue>)全面对比

    C#中数组.集合(ArrayList).泛型集合List<T>.字典(dictionary<TKey,TValue>)全面对比 为什么把这4个东西放在一起来说,因为c#中的这4 ...

  4. MySQL 中的共享锁和排他锁的用法

    在 MySQL 中的行级锁.表级锁和页级锁中,咱们介绍过,行级锁是 MySQL 中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突.行级锁分为共享锁和排他锁两种,本文将详细介绍共享锁和排他锁的概 ...

  5. Qt去掉treeview项的焦点虚线

    项目做到后期,进行局部美化的时候发现了问题,在treeview框选择状态下会有虚线. 其实,不仅是treeview,tableview,listview,乃至button在有焦点的情况下,都会出现虚线 ...

  6. TCP/IP协议的工作流程

    1.在源主机上,应用层将一串应用数据流向下传输给传输层 2.传输层将应用数据截流成分组,并加上TCP报头形成TCP段,向下递交给网络层 3.在网络层给TCP段加上包括源主机,目的主机IP地址的IP报头 ...

  7. 2019秋季PAT甲级_C++题解

    2019 秋季 PAT (Advanced Level) C++题解 考试拿到了满分但受考场状态和知识水平所限可能方法不够简洁,此处保留记录,仍需多加学习.备考总结(笔记目录)在这里 7-1 Fore ...

  8. 学习C语言深入解剖笔记之关键字的秘密

    C语言关键字的秘密 重点说明: 1.if(略) 2.void ①C语言规定只有相同类型的指针才可以相互赋值 ②void*指针作为左值用于“接收”任意类型的指针 ③void*指针作为右值赋值给其它指针时 ...

  9. (转)Nginx+rtmp+ffmpeg搭建流媒体服务器

    (1)下载第三方扩展模块nginx-rtmp-module # mkdir module && cd module //创建一个存放模块的目录 # wget https://githu ...

  10. mysql中常见正则表达式的应用

    查找name字段中以'st'为开头的所有数据: mysql> SELECT name FROM person_tbl WHERE name REGEXP '^st'; 查找name字段中以'ok ...