CSP 模拟9

news/2024/10/8 16:49:56

CSP 模拟9

我也不明白学校模拟赛什么命名逻辑,凑合着看吧

最唐的一集

邻面合并

这个直接状压就做完了,赛时早早想到做法,但是因为自己太唐把 \(0\) 写成 \(1\),在优秀大样例的助攻下挂掉 \(50\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
llt dp[110][1<<9],n,m,mp[110][110],ans=1e18;
bool check(llt x,llt y)
{for(int i=1;i<m;i++){if(mp[x][i]==0&&mp[x][i+1]==0&&((y>>i-1)&1))return false;if(mp[x][i]!=mp[x][i+1]&&!((y>>i-1)&1))return false;}return true;
}
llt solve(llt a,llt b,llt x,llt y)
{llt tot=0,L;map<pair<llt,llt>,llt> P;vector<llt> vec;vec.push_back(0);for(int i=1;i<m;i++)if((x>>i-1)&1)vec.push_back(i);vec.push_back(m);L=vec.size();for(int i=1;i<L;i++)    P[make_pair(vec[i-1],vec[i])]=mp[a][vec[i]]+1;vector<llt>().swap(vec);vec.push_back(0);for(int i=1;i<m;i++)if((y>>i-1)&1)vec.push_back(i);vec.push_back(m);L=vec.size();for(int i=1;i<L;i++)    if(P[make_pair(vec[i-1],vec[i])]==2&&mp[b][vec[i]]==1)continue;else if(mp[b][vec[i]]==1)tot++;return tot;
}
int main()
{freopen("merging.in","r",stdin);freopen("merging.out","w",stdout);scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%lld",&mp[i][j]);memset(dp,0x3f,sizeof(dp));for(int j=0;j<(1<<m-1);j++)   if(check(1,j))  dp[1][j]=solve(0,1,0,j);for(int i=2;i<=n;i++)for(int j=0;j<(1<<m-1);j++) {if(!check(i,j)) continue;for(int k=0;k<(1<<m-1);k++)dp[i][j]=min(dp[i][j],dp[i-1][k]+solve(i-1,i,k,j));if(i==n)    ans=min(ans,dp[i][j]);} printf("%lld\n",ans);return 0;
}

光线追踪

简单线段树题,赛时再次因为少特判挂掉 \(70\),我是唐唐大王

把一个矩形拆成横竖两条线段,
直接线段树维护斜率,离散化就好了,发现这玩意只需要单点查询,所以根本不用改太多东西

代码写得很垃圾,别看

点击查看代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
using ldb=long double;
const ldb eps=1e-32; 
const llt N=200100;
llt Q,siz,ans1[N],ans2[N];
struct OPT{llt op,a,b,c,d,LA,RA,C;ldb La,Ra;}q[N];
ldb us[N<<1],L1,L2;
bool cmp(ldb A,ldb B){return B-A>eps;}
bool Cmp(ldb A,ldb B){return B-A<eps&&B-A>-eps;}
struct SEGMENT_TREE
{#define mid ((st+ed)>>1)llt tag[N<<4];void push_down(llt now){if(q[tag[now<<1]].C>q[tag[now]].C||(q[tag[now]].C==q[tag[now<<1]].C&&tag[now]>tag[now<<1]))  tag[now<<1]=tag[now];if(q[tag[(now<<1)|1]].C>q[tag[now]].C||(q[tag[now]].C==q[tag[(now<<1)|1]].C&&tag[now]>tag[(now<<1)|1]))  tag[(now<<1)|1]=tag[now];}void change(llt now,llt st,llt ed,llt x,llt y,llt P){if(x<=st&&ed<=y){if(q[P].C<q[tag[now]].C||(q[P].C==q[tag[now]].C&&P>tag[now]))  tag[now]=P;return;}push_down(now);if(x<=mid)  change(now<<1,st,mid,x,y,P);if(y>mid)   change((now<<1)|1,mid+1,ed,x,y,P);}llt find(llt now,llt st,llt ed,llt x){if(st==ed)  return tag[now];push_down(now);if(x<=mid)  return find(now<<1,st,mid,x);else        return find((now<<1)|1,mid+1,ed,x);}
}s_tree,Y_tree;
int main()
{freopen("raytracing.in","r",stdin);freopen("raytracing.out","w",stdout);scanf("%lld",&Q);for(int i=1;i<=Q;i++){scanf("%lld",&q[i].op);if(q[i].op==1)  {scanf("%lld%lld%lld%lld",&q[i].a,&q[i].b,&q[i].c,&q[i].d);if(q[i].b==0)   continue;q[i].La=(ldb)q[i].a*1e9/q[i].b;q[i].Ra=(ldb)q[i].c*1e9/q[i].b;us[++siz]=q[i].La,us[++siz]=q[i].Ra;}else    {scanf("%lld%lld",&q[i].a,&q[i].b);if(q[i].b==0)   continue;q[i].La=us[++siz]=(ldb)q[i].a*1e9/q[i].b;}}sort(us+1,us+1+siz,cmp);siz=unique(us+1,us+1+siz,Cmp)-us-1;q[0].b=1e18;for(int i=0;i<=Q;i++)   q[i].C=q[i].b;for(int i=1;i<=Q;i++)  if(q[i].op==1&&q[i].b!=0)  q[i].LA=lower_bound(us+1,us+1+siz,q[i].La,cmp)-us-1,q[i].RA=lower_bound(us+1,us+1+siz,q[i].Ra,cmp)-us-1;else if(q[i].b!=0)    q[i].LA=lower_bound(us+1,us+1+siz,q[i].La,cmp)-us-1;for(int i=1;i<=Q;i++){if(q[i].op==1&&q[i].b!=0)  s_tree.change(1,0,siz,q[i].LA,q[i].RA,i);else if(q[i].b!=0)   ans1[i]=s_tree.find(1,0,siz,q[i].LA);}//---------------------------------------------------------------------------siz=0;for(int i=1;i<=Q;i++){if(q[i].op==1)  {//assert(q[i].a);if(q[i].a==0)   continue;q[i].La=(ldb)q[i].b*1e9/q[i].a;q[i].Ra=(ldb)q[i].d*1e9/q[i].a;us[++siz]=q[i].La,us[++siz]=q[i].Ra;}else if(q[i].a!=0)  q[i].La=us[++siz]=(ldb)q[i].b*1e9/q[i].a;}sort(us+1,us+1+siz,cmp);siz=unique(us+1,us+1+siz,Cmp)-us-1;q[0].a=1e18;for(int i=0;i<=Q;i++)   q[i].C=q[i].a;for(int i=1;i<=Q;i++)  if(q[i].op==1&&q[i].a!=0)  q[i].LA=lower_bound(us+1,us+1+siz,q[i].La,cmp)-us-1,q[i].RA=lower_bound(us+1,us+1+siz,q[i].Ra,cmp)-us-1;else if(q[i].a!=0) q[i].LA=lower_bound(us+1,us+1+siz,q[i].La,cmp)-us-1;for(int i=1;i<=Q;i++){if(q[i].op==1&&q[i].a!=0)  Y_tree.change(1,0,siz,q[i].LA,q[i].RA,i);else if(q[i].a!=0) ans2[i]=Y_tree.find(1,0,siz,q[i].LA);}for(int i=1;i<=Q;i++)if(q[i].op==2){if(ans1[i]==0||ans2[i]==0)  ans1[i]^=ans2[i],printf("%lld\n",ans1[i]);else{L1=(ldb)q[ans1[i]].b/q[i].b;L2=(ldb)q[ans2[i]].a/q[i].a;if(L2-L1>eps) printf("%lld\n",ans1[i]);else if(L1-L2>eps)   printf("%lld\n",ans2[i]);else    printf("%lld\n",max(ans1[i],ans2[i]));}}return 0;
}

百鸽笼

考UNR D2T2 是吧
暂时没学会jijidawang讲的egf做法,写容斥

发现所求可以直接容斥出来,钦定一列鸽笼,求它比 \(k\) 列不同的鸽笼早填满的概率

我们枚举所有不同的集合 \(S\) 之后子集反演就能直接求出最后一个填满的概率

现在要求的是对每列鸽笼 \(i\),其比 \(S\) 列鸽笼都早填满的概率

这时候如果有管理员进入其他列鸽笼就无所谓了,直接忽略,一个合法的进入序列是由 \(a_i\)\(i\) 和少于 \(a_j\)\(j\)(\(j \in S\))组成的,且由 \(i\) 结尾(因为后面全省略了)

序列个数这时候直接枚举每个 \(a_j\) 插板就好了,也可以直接用多重集排列数,而总的序列不好求,我们引入一维 \(L\),是序列的总长,发现所有序列有 \((|S|+1)^L\)

你发现当钦定这 \(j\) 列鸽笼的集合 \(S\) 时概率为 \(\dfrac{f_{i,S}}{(|S|+1)^L}\),枚举所有集合去做就是指数暴力了,直接背包就好了

但是容斥的时候当 \(|S|\) 一样的时候系数都一样,所以设 \(dp_{i,k,d}\) 是选到 \(i\)\(|S|=k\),长度为 \(d\),转移就是

\[dp_{i,k,d}=\sum_u \dbinom{d}{u} dp_{i-1,k-1,d-u} \]

最后把 \(i\) 插进去就好了 $$dp_{n,k,d}=\tbinom{d-1}{u-1}dp_{n,k,d-a_i}$$

乘上系数就是 \(O(n^2 \sum a_i \max{a_i})\)

背包加上回退就优化到 \(O(n \sum a_i \max{a_i})\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
const llt N=40,M=2000;
const llt mod=998244353;
llt n,m,a[N],inv[M],tms[M],invt[M],dp[2][N][M],tmp[N][M],ans[N];
llt qpow(llt x,llt y)
{llt ret=1;while(y){if(y&1) ret=ret*x%mod;x=x*x%mod;y>>=1;}return ret;
}
llt C(llt A,llt B){return tms[B]*invt[A]%mod*invt[B-A]%mod;}
int main()
{freopen("c.in","r",stdin);freopen("c.out","w",stdout);scanf("%lld",&n);for(int i=1;i<=n;i++)  scanf("%lld",&a[i]),m+=a[i];for(int i=1;i<=m;i++)   inv[i]=qpow(i,mod-2);tms[0]=invt[0]=1;for(int i=1;i<=m;i++)  tms[i]=tms[i-1]*i%mod,invt[i]=invt[i-1]*inv[i]%mod;llt is=0;memset(dp,0,sizeof(dp));dp[is][0][0]=1;for(int j=1;j<=n;j++){is^=1;for(int k=0;k<=n;k++)   for(int d=0;d<=m;d++)   dp[is][k][d]=dp[is^1][k][d];for(int k=1;k<=n;k++)for(int d=0;d<=m;d++)for(int u=0;u<a[j]&&u<=d;u++)dp[is][k][d]=(dp[is][k][d]+dp[is^1][k-1][d-u]*C(u,d)%mod)%mod;}for(int i=1;i<=n;i++){memset(tmp,0,sizeof(tmp));for(int k=0;k<=n;k++)   for(int d=0;d<=m;d++)   tmp[k][d]=dp[is][k][d];for(int k=1;k<=n;k++)for(int d=0;d<=m;d++)for(int u=0;u<a[i]&&u<=d;u++)tmp[k][d]=(tmp[k][d]-tmp[k-1][d-u]*C(u,d)%mod+mod)%mod;for(int k=0;k<=n;k++)for(int d=m;d>=a[i];d--)tmp[k][d]=tmp[k][d-a[i]]*C(a[i]-1,d-1)%mod;ans[i]=1;for(int j=1;j<=n;j++)   for(int k=a[i];k<=m;k++)if(j&1) ans[i]=(ans[i]-tmp[j][k]*qpow(qpow(j+1,k),mod-2)%mod+mod)%mod;else    ans[i]=(ans[i]+tmp[j][k]*qpow(qpow(j+1,k),mod-2)%mod+mod)%mod;printf("%lld ",ans[i]);}return 0;
}

滑稽树下你和我

二分答案

思考特殊性质,发现只要在点上转移就好了,关键在每一时刻至少有一个点在端点上

对于正解,将边也拆成点,算点到线段距离就好了,因为当两个点所在线段没有改变的话只要首尾状态都满足二分值则整个过程满足

所以直接一样做

但是这样常数太大了,可以学习一下官方题解状态设计

这是一份采用官方题解优秀状态设计的代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
using ldb=double;
const ldb eps=1e-9; 
const llt N=1010;
llt n,stx,sty,a[N],b[N],in[N],head[N],to[N<<1],nxt[N<<1],siz=1;ldb x[N],y[N],l=0,r=10000000,mid;bool vis[N][N],dp[N][N];
inline void add(llt st,llt ed){to[++siz]=ed,nxt[siz]=head[st],head[st]=siz;}
inline ldb Dis(ldb xa,ldb ya,ldb xb,ldb yb){return sqrt((xb-xa)*(xb-xa)+(yb-ya)*(yb-ya));}
inline ldb Dis(ldb X,ldb Y,ldb xa,ldb ya,ldb xb,ldb yb)
{ldb len=Dis(xa,ya,xb,yb),Lx=xb-xa,Ly=yb-ya,Vx=xb-X,Vy=yb-Y,Q;Q=(Vx*Lx+Vy*Ly)/len;if(Q<=0) return Dis(X,Y,xb,yb);if(Q>=len)   return Dis(X,Y,xa,ya);return sqrt(Dis(X,Y,xb,yb)*Dis(X,Y,xb,yb)-Q*Q);
}
bool check(ldb is)
{memset(vis,0,sizeof(vis));queue<llt> A,B;llt X,Y,tmp;for(int i=head[stx];i;i=nxt[i]) A.push(sty),B.push(i>>1),vis[sty][i>>1]=1;for(int i=head[sty];i;i=nxt[i]) A.push(stx),B.push(i>>1),vis[stx][i>>1]=1;while(!A.empty()){X=A.front(),A.pop(),Y=B.front(),B.pop();if(in[X]==1)if((in[to[Y<<1]]==1&&is-Dis(x[X],y[X],x[to[Y<<1]],y[to[Y<<1]])>eps)||(in[to[Y<<1|1]]==1&&is-Dis(x[X],y[X],x[to[Y<<1|1]],y[to[Y<<1|1]])>eps))  return 1;for(int i=head[X];i;i=nxt[i]){if(is-Dis(x[to[i]],y[to[i]],x[to[Y<<1]],y[to[Y<<1]],x[to[Y<<1|1]],y[to[Y<<1|1]])>eps&&!vis[to[i]][Y])vis[to[i]][Y]=1,A.push(to[i]),B.push(Y);tmp=to[Y<<1];if(is-Dis(x[tmp],y[tmp],x[to[i]],y[to[i]],x[to[i^1]],y[to[i^1]])>eps&&!vis[tmp][i>>1])vis[tmp][i>>1]=1,A.push(tmp),B.push(i>>1);tmp=to[Y<<1|1];if(is-Dis(x[tmp],y[tmp],x[to[i]],y[to[i]],x[to[i^1]],y[to[i^1]])>eps&&!vis[tmp][i>>1])vis[tmp][i>>1]=1,A.push(tmp),B.push(i>>1);}}return 0;
}
int main()
{freopen("tree.in","r",stdin);freopen("tree.out","w",stdout);scanf("%lld%lld%lld",&n,&stx,&sty);for(int i=1;i<=n;i++)   scanf("%lf%lf",&x[i],&y[i]);for(int i=1;i<=n;i++)   scanf("%lld%lld",&a[i],&b[i]),in[a[i]]++,in[b[i]]++,add(a[i],b[i]),add(b[i],a[i]);l=Dis(x[stx],y[stx],x[sty],y[sty]);for(int i=1;i<=40;i++){mid=(l+r)/2;if(check(mid))  r=mid;else l=mid;   }printf("%.16lf",l);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/69055.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

南沙C++信奥赛陈老师解一本通题 1297:公共子序列

​【题目描述】我们称序列Z=<z1,z2,...,zk>Z=<z1,z2,...,zk>是序列X=<x1,x2,...,xm>X=<x1,x2,...,xm>的子序列当且仅当存在严格上升的序列<i1,i2,...,ik><i1,i2,...,ik>,使得对j=1,2,...,k,有xij=zjxij=zj。比如Z=<a,b,f,c> 是X=&l…

语音生成公司 ElevenLabs 估值达 30 亿美元;OpenAI Realtime API 很好也很贵丨RTE 开发者日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编…

万兆加速计算卡设计资料保存:372-基于XC7VX690T的万兆光纤、双FMC扩展的综合计算平台 RISCV 芯片验证平台

一、板卡概述 基于V7的高性能PCIe信号处理板,板卡选用Xilinx 公司Virtex7系列FPGA XC7VX690T-2FFG1761C为处理芯片,板卡提供两个标准FMC插槽,适用于高性能采集、回放以及相关处理。通过连接不同的FMC子卡的方式,可实现不同形式的数据采集、回放、处理的功能模块。板卡…

中电金信:源启数据建模平台:建模效率和管理精细度进一步提升

​源启数据建模平台是源启数据资产平台面向数据仓库等大型数据模型构建专门打造的模型设计工具。它以需求牵引模型动态演进,持续变更模型适应业务变化,并以Web和图形化方式,提供正向、逆向建模能力,高效复用模型资产和构建大型数据模型。同时,秉承“建模即治理”的思想,在…

是用python脚本清理reids连接

背景:测试环境的redis不知道咋回事突然无法连接,服务器登录查了一下发现连接数用完了。研发说雨女无瓜,测试环境删了没事,正事要紧赶紧恢复。得嘞!> info clients # Clients connected_clients:9997 # 连接中的数量 client_recent_max_input_buffer:54366 client_rece…

在Cucumber中应用 PicoContainer容器实现组件的实例化

通过 PicoContainer 这个轻量级的DI(Dependency Injection)组件容器进行组件的实例化, 相关介绍参考:http://picocontainer.com/introduction.html step1:定义一个ScenarioContext类 step2:添加jar依赖 implementation io.cucumber:cucumber-picocontainer:7.2.3 step3:…

查看交叉编译器的默认选项

1. 新建C文件mfloat.c#include <stdio.h> int main(void) { double a,b,c;a = 23.5436;b = 323.2348;c = b/a;printf("the result = %f\n", c);printf("hello world !\n");return 0; }2. 是 -v 选项 3. 显示结果如下

StarRocks模型表(一)

主键表优势:支撑实时数据更新的同时,也能保证高效的复杂即席查询性能 主键表中的主键具有唯一非空约束,用于唯一标识数据行,如果新数据的主键值与表中原数据的主键值相同,则存在唯一约束冲突,此时新数据会替代原数据应用场景实时对接事务型数据至StarRocks。事务型数据库…