noip模拟33[进阶啦啦啦]
noip模拟33 solutions
不知道该咋说,这场考试其实是我这三四场以来最最最最最顺心的一场了
为啥呢?因为我这回思考有很多结果,得到了脑袋的回复
就是你想了半个小时就有了一点点头绪,那感觉就是"妙哉"
但是分数却不如人意,只有100pts,挂掉了55pts
按照现在的状态,下次肯定能A题
T1 Hunter
这个题还是一眼就有45pts,轻轻的状压一下,再加上记忆化搜索
半个小时45pts到手。
45pts·状压
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e5+5;
const ll mod=998244353;
int n;
ll w[N],dp[1<<20];
ll ksm(ll x,ll y){
ll ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;
y>>=1;
}
return ret;
}
ll dfs(int x,int s){
if(x==n+1)return 1;
if(dp[s])return dp[s];
ll tmp=0;
for(re i=1;i<=n;i++){
if((s>>i-1)&1)continue;
tmp=(tmp+w[i])%mod;
}
ll bas=ksm(tmp,mod-2);
for(re i=1;i<=n;i++){
if((s>>i-1)&1)continue;
if(i==1)dp[s]=(dp[s]+w[i]*bas%mod*x%mod)%mod;
else dp[s]=(dp[s]+w[i]*bas%mod*dfs(x+1,s|(1<<i-1)%mod))%mod;
}
return dp[s];
}
signed main(){
scanf("%d",&n);
for(re i=1;i<=n;i++)
scanf("%lld",&w[i]);
printf("%lld",dfs(1,0));
}
但是接下来的质的飞跃就比较难受,但是看完题解之后整个人都傻掉了
所以说,对于期望这个东西咋转移都没事
毕竟这个期望是具有线性性的,怎么加都可以,然后这个题就直接做出来了
我们知道第一个猎人死在第几次,那么就是在他前面死的人的个数+1
下面就是求期望有多少人死在他前面,
如果当前这个人还没有死,那么这个人死在1号猎人之前的概率就是\(\frac{w_i}{w_1+w_i}\)
因为每死一个就会造成1的贡献,所以期望就是概率
不需要考虑别人的死法,因为这个i包含了所有的其他的猎人
这样考虑的原因还有一个,就是死的概率和谁开枪没有关系,只和当前谁剩下有关
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e5+5;
const ll mod=998244353;
int n;
ll w[N],dp[1<<20];
ll ksm(ll x,ll y){
ll ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;
y>>=1;
}
return ret;
}
ll ans;
signed main(){
scanf("%d",&n);
for(re i=1;i<=n;i++)
scanf("%lld",&w[i]);
for(re i=2;i<=n;i++){
ans=(ans+w[i]*ksm(w[i]+w[1],mod-2)%mod)%mod;
}
printf("%lld",ans+1);
}
这个题其实非常的水,只要充分理解期望就好了。。
T2 Defence
我这个题考场上一眼切了,直接线段树合并+维护最长区间
这个题之前做过好多次了
这次就维护区间内最长的0就好了。。。。不难吧
注意维护的时候,最后的答案是max(区间内最长的,左右最长的之和)这个可以看代码实现
因为初始全部是0,所以这里的pushup有一些玄学,
如果看不懂可以去网上求救一下其他人的维护1的长度的做法
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e5+5;
int n,m,q;
int to[N],nxt[N],head[N],rp;
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
struct XDS{
int mmx[N*80],rmx[N*80],lmx[N*80];
int ls[N*80],rs[N*80];
int seg;
void pushup(int x,int l,int r){
if(!ls[x]&&!rs[x])return ;
int mid=l+r>>1;
if(ls[x]&&rs[x]){
mmx[x]=max(lmx[rs[x]]+rmx[ls[x]],max(mmx[rs[x]],mmx[ls[x]]));
lmx[x]=lmx[ls[x]];
if(lmx[ls[x]]==mid-l+1)lmx[x]=lmx[ls[x]]+lmx[rs[x]];
rmx[x]=rmx[rs[x]];
if(rmx[rs[x]]==r-mid)rmx[x]=rmx[rs[x]]+rmx[ls[x]];
}
if(ls[x]&&!rs[x]){
mmx[x]=mmx[ls[x]];
lmx[x]=lmx[ls[x]];
if(lmx[ls[x]]==mid-l+1)lmx[x]=r-l+1;
rmx[x]=rmx[ls[x]]+r-mid;
}
if(!ls[x]&&rs[x]){
mmx[x]=mmx[rs[x]];
lmx[x]=lmx[rs[x]]+mid-l+1;
rmx[x]=rmx[rs[x]];
if(rmx[rs[x]]==r-mid)rmx[x]=r-l+1;
}
return ;
}
void ins(int &x,int l,int r,int pos){
if(!x)x=++seg;
if(l==r)return ;
int mid=l+r>>1;
if(pos<=mid)ins(ls[x],l,mid,pos);
else ins(rs[x],mid+1,r,pos);
pushup(x,l,r);
return ;
}
int merge(int x,int y,int l,int r){
if(!x||!y)return x+y;
if(l==r)return x;
int mid=l+r>>1;
ls[x]=merge(ls[x],ls[y],l,mid);
rs[x]=merge(rs[x],rs[y],mid+1,r);
pushup(x,l,r);
return x;
}
}xds;
int rt[N],ans[N];
void dfs(int x){
for(re i=head[x];i;i=nxt[i]){
int y=to[i];dfs(y);
rt[x]=xds.merge(rt[x],rt[y],1,m);
}
if(!rt[x])ans[x]=-1;
else ans[x]=max(xds.mmx[rt[x]],xds.lmx[rt[x]]+xds.rmx[rt[x]]);
}
signed main(){
scanf("%d%d%d",&n,&m,&q);
for(re i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
add_edg(x,y);
}
for(re i=1;i<=q;i++){
int x,y;
scanf("%d%d",&x,&y);
xds.ins(rt[x],1,m,y);
}
dfs(1);
for(re i=1;i<=n;i++){
printf("%d\n",ans[i]);
}
}
所以说为什么我只有45pts嘞???
因为我没有判断-1,但是其实挺冤的。
考场上我明明自己造了一组数据有-1的情况,当时我的\(code\)输出的是0
然后我暴怒
这输出0怎么行呢,让他变成m
一顿乱搞,把所有的-1全判成了m,考后直接把m改成-1,\(AC\;AC\;AC\;AC\)
T3 Connect
最近总是在考试的时候遇到一些状压神题,昨天是二维,今天是带其他变量
真难!!!
理解了就非常的简单
我们要将所有的点都加入到当前的状态内,所以我们的dp第一维一定是点集
既然是dp,那么我们就可以直接枚举所有状态,而且这个题复杂度极其的小
设dp[i][j]表示当前点集为i,1-n的这个链的结尾是j,
当然你可能会认为,有可能j他不在这个链上啊啊,
大哥,这都是dp了,不在链上他能转移过去,枚举就完事了,而且你当时也不知道谁在谁不在
我们有两种情况一种是在当前点直接并入其他点集,但是这个点集中的点只可以跟当前j连边
为啥不可以跟前边连啊啊啊?因为前面的在前面已经计算过了,所以这里面有好多无用状态
但是他方便了你的转移
另外一种就之在j上再接一个点k,那么加入这个点后的点集的端点就是k啦,
为啥不能是j,因为你前面还会计算k在前面,j接在k后面的情况
dp就是dp,不需要考虑那么多好吧。。。。
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=20;
int n,m;
int dis[N][N];
int sum[1<<15];
int dp[1<<15][16],val[1<<15][16];
signed main(){
scanf("%d%d",&n,&m);
for(re i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
dis[x][y]=dis[y][x]=z;
}
for(re i=1;i<(1<<n);i++)
for(re j=1;j<=n;j++)
for(re k=j+1;k<=n;k++)
if(((i>>j-1)&1)&&((i>>k-1)&1))sum[i]+=dis[j][k];
for(re i=1;i<(1<<n);i++)
for(re j=1;j<=n;j++){
if((i>>j-1)&1)continue;
for(re k=1;k<=n;k++)
if(((i>>k-1)&1)&&dis[j][k])val[i][j]+=dis[j][k];
}
memset(dp,0x8f,sizeof(dp));
dp[1][1]=0;
for(re i=1;i<(1<<n);i++){
for(re j=1;j<=n;j++){
if(dp[i][j]==0x8f8f8f8f)continue;
for(re k=1;k<=n;k++){
if((i>>k-1)&1)continue;
dp[i|(1<<k-1)][k]=max(dp[i|(1<<k-1)][k],dp[i][j]+dis[j][k]);
}
int tmp=(i^((1<<n)-1));
for(re k=tmp;k;k=(k-1)&tmp){
dp[i|k][j]=max(dp[i|k][j],dp[i][j]+val[k][j]+sum[k]);
}
}
}
//cout<<sum[(1<<n)-1]<<" "<<dp[(1<<n)-1][n]<<endl;
printf("%d",sum[(1<<n)-1]-dp[(1<<n)-1][n]);
}
noip模拟33[进阶啦啦啦]的更多相关文章
- noip模拟33
\(\color{white}{\mathbb{失足而坠千里,翻覆而没百足,名之以:深渊}}\) 这场考试的时间分配非常不科学 开题试图想 \(t1\) 正解,一个半小时后还是只有暴力,特别惊慌失措 ...
- Noip模拟33垫底反思 2021.8.8
T1 Hunter 考场上没写$%p$挂了25分.也是很牛皮,以后打完过了样例一定要检查 因为样例太小了......很容易忘记%%%% 正解随便手模就出来了. 1 #include<bits/s ...
- 2021.8.8考试总结[NOIP模拟33]
T1 Hunter 考场上一看期望直接状压拿了$45pts$跑了.结果正解只用$4$行? 把问题转化为一号猎人之前死的猎人数的期望加一. 期望的线性性. 对每个猎人$i$,$w_i+w_1$种情况中有 ...
- NOIP模拟 33
苏轼三连一脸懵逼 然而既惨者就是没素质 T1是正解思路 然而因为直接从暴力修改过来并且忘了把求约数改成求质约数并且由于快速幂打的有缺陷等 没 有 A C ! 如 果 A C rank1就是俺的了! ( ...
- [NOIP模拟33]反思+题解
又考了一次降智题…… 拿到T1秒出正解(可能是因为我高考数学数列学的海星?),分解质因数以后用等比数列求和计算每个因子的贡献.但是当时太过兴奋把最后的$ans \times =$打成了$ans +=$ ...
- 8.8考试总结(NOIP模拟33)[Hunter·Defence·Connect]
无法逃避的是自我,而无法挽回的是过去. 前言 还算可以,不过 T1 少 \(\bmod\) 了一下挂了 25pts,T2 没看清题面挂了 27pts. 下回注意吧.. T1 Hunter 解题思路 感 ...
- [考试总结]noip模拟33
连炸两场... 伤心... 第一个题目首先因为有期望坐镇,然后跳过... 然后第二个题目发现题目挺绕的,然后转化了一句话题意,然后..... \(\huge{\text{转化错了!!!!}}\) 然而 ...
- NOIP 模拟 $33\; \rm Connect$
题解 状压 \(\rm DP\). 从 \(1\) 到 \(n\) 一共只要一条路径,那么就是一条链,只要维护一个点集和当前链的末尾就行. 设 \(\rm dp_{i,j}\) 为 \(i\) 的点集 ...
- NOIP 模拟 $33\; \rm Defence$
题解 \(by\;zj\varphi\) 题意就是维护 \(\rm max\{01mx,01l+01r\}\) 就是最长连续的一段 \(0\),左右 \(0\) 区间的加和. 可以启发式合并,也可以直 ...
随机推荐
- HTTP Cookies知识-查看、发送、获取、返回
我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 HTTP Cookies是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求 ...
- Linux 中使用 QT Charts 显示温度传感器
前一篇笔记中实现了QT的Label控件显示CPU的温度,只能显示当前的温度,并不能反映CPU温度的变化情况,现在来实现使用QT Charts的曲线图实现一个实时曲线来显示CPU的温度. 添加对Qt C ...
- 通过Cloudflare API进行CDN刷新
1.Cloudflare CDN刷新说明 1.Cloudfalre同Akamai一样,只有刷新,没有预热的概念. 2.通过Cloudflare API进行刷新,需要用到登录用户的[邮箱][api密钥] ...
- OpenGL 实用攻关 001 准备(开题)
开篇 这里是OpenGL学习中的随笔,会大致讲述定下的目标需求,思路和贴出认为的关键代码以及git仓库地址.会选择性的讲述途中遇到的陷阱,和注意点. 一些资源 笔者是windows 操作系统 VS 2 ...
- Docker Swarm介绍
1 什么是swarmSwarm是Docker公司推出的docker集群管理平台,它将一群Docker主机变成了一台单一的虚拟Docker主机.Swarm使用标准的Docker API接口,因此,任何支 ...
- Tomcat:tomcat部署war包配置SSL访问
Linux-CentOS7部署 war放置 war放到tomcat的webapps目录内 修改配置 修改tomcat的server.xml文件 HTTP: 找到Connector元素,修改端口 HTT ...
- 在Java中如何高效判断数组中是否包含某个元素
如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...
- php 基于redis使用令牌桶算法 计数器 漏桶算法 实现流量控制
通常在高并发和大流量的情况下,一般限流是必须的.为了保证服务器正常的压力.那我们就聊一下几种限流的算法. 计数器计数器是一种最常用的一种方法,在一段时间间隔内,处理请求的数量固定的,超的就不做处理. ...
- 剑指offer 37-42
37. 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 思路: 1.平衡二叉树的定义为,当为空树或左右子树高度小于等于1,同时左右子树都要为平衡二叉树. 2.先分别求出左右子树的高度,比较高度差,如果 ...
- 多线程笔记-CancellationToken(取消令牌)
介绍 为什么需要CancellationToken?因为Task没有方法支持在外部取消Task,只能通过一个公共变量存放线程的取消状态,在线程内部通过变量判断线程是否被取消,当Cancella ...