2024.12.15 THUPC2025初赛

Solved: 6/13

Rank: 295


300 多人过的网络流题没思路,直接从 200- 掉到 300-……


M. 好成绩

致敬主=6()

print(83)

C. Harmful Machine Learning

题意:\(n\) 个格子排成一列,初始棋子位于第 \(x\) 个格子。两人先后操作,每一轮先手可交换两个格子的数(可以不换),后手可将棋子移动到相邻格子(可以不动)或结束。
先手希望结束的时候棋子所在的格子中的数最小,后手希望最大,求最优决策下的答案。

一步之后,先手就可以将最小的三个数都移到后手的格子以及相邻两个格子的位置。因此后手的唯一机会就在第一步。
先手针对后手的第一步可以将最小值移到到后手下一步能到的三个格子中,因此后手第一步只能取到这三个格子中第二大的值。
答案就是 \(\max\{a_{(3)},\{a_{x-1},a_x,a_{x+1}\}_{(2)}\}\)

特判 \(n=1,n=2\)\(x=1,x=n\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()void solve(){int n,x;cin>>n>>x,--x;vector<int> a(n);for(int i=0;i<n;++i)cin>>a[i];vector<int> b(a);sort(all(b));if(n<=3){cout<<b[n-1]<<'\n';}else{if(x==0){cout<<max(min(a[0],a[1]),b[2])<<'\n';}else if(x==n-1){cout<<max(min(a[n-1],a[n-2]),b[2])<<'\n';}else{vector<int> c({a[x-1],a[x],a[x+1]});sort(all(c));cout<<max(c[1],b[2])<<'\n';}}
}int main(){ios::sync_with_stdio(0);cin.tie(0);int T;cin>>T;while(T--)solve();
}

I. 乒乓球赛

题意:两人打乒乓球,10平前先得11分者胜,10平后先超对方2分者胜。已知比赛过程中的一些比分情况(顺序可能颠倒,即 3:5 念成 5:3),求符合已知条件的方案数。\(n\leq 10^5\)

dp,\(f_i,g_i\) 表示第 \(i\) 轮比分没颠倒/颠倒的方案数。转移形如 \(f_j\times F(a_j,b_j,a_i,b_i)\rightarrow f_i\)。其中 \(F(a,b,c,d)\) 是从 \((a,b)\)\((c,d)\) 的方案数。

如果两个状态都没到 10 平,直接组合数即可(\(11\) 视为 \(10\),因为赢的一球必然是最后一球);

如果两个状态都过了 10 平,则 \(a-b,c-d\) 取值都只能是 \(-1,0,1\)\(2\) 视为 \(1\)\(-2\) 视为 \(-1\))。直接预处理出这部分 dp 即可。

如果前面没过后面过了,则一定存在某一时刻比分是 10 平,两段分开乘即可。

注意特判各种无解不合法情况。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()const int N=1e5+5,mod=998244353;int c[21][21];
ll h[N][3][3];
void init(){for(int i=0;i<=20;++i){c[i][0]=1;for(int j=1;j<=i;++j)c[i][j]=c[i-1][j]+c[i-1][j-1];}h[0][0][0]=h[0][1][1]=h[0][2][2]=1;int m=1e5;for(int i=0;i<=m;++i)for(int j=0;j<3;++j){(h[i+1][j][0]+=h[i][j][1])%=mod;(h[i+1][j][1]+=h[i][j][0])%=mod;(h[i+1][j][1]+=h[i][j][2])%=mod;(h[i+1][j][2]+=h[i][j][1])%=mod;}
}ll F(int x1,int y1,int x2,int y2){if(x2<x1||y2<y1)return 0;if(x2+y2<=20){x2=min(x2,10),y2=min(y2,10);return c[x2+y2-x1-y1][x2-x1];}if(x1+y1>=20){int s=x2+y2-x1-y1,d1=x1-y1,d2=x2-y2;if(d2==2)--s,--d2;if(d2==-2)--s,++d2;return h[s][d1+1][d2+1];}return F(x1,y1,10,10)*F(10,10,x2,y2)%mod;
}ll solve(){int n;cin>>n;vector<int> a(n+1),b(n+1);vector<ll> f(n+1),g(n+1);for(int i=1;i<=n;++i){cin>>a[i]>>b[i];if(a[i]<b[i])swap(a[i],b[i]);}if(n<=20){if(a[n]!=-1&&(a[n]!=11||b[n]!=n-11))return 0;a[n]=11,b[n]=n-11;}else{if(n%2==1)return 0;if(a[n]!=-1&&(a[n]!=n/2+1||b[n]!=n/2-1))return 0;a[n]=n/2+1,b[n]=n/2-1;}auto chk=[=](int x,int y)-> bool {if(x+y<=20)return x>10;return x-y>1;};f[0]=1,g[0]=0;for(int i=1,j=0;i<=n;++i){if(a[i]==-1)continue;if(a[i]+b[i]!=i)return 0;if(chk(a[i],b[i])&&i<n)return 0;f[i]=(f[j]*F(a[j],b[j],a[i],b[i])+g[j]*F(b[j],a[j],a[i],b[i]))%mod;if(a[i]!=b[i])g[i]=(f[j]*F(a[j],b[j],b[i],a[i])+g[j]*F(b[j],a[j],b[i],a[i]))%mod;j=i;}return (f[n]+g[n])%mod;
}int main(){init();ios::sync_with_stdio(0);cin.tie(0);int T;cin>>T;while(T--)cout<<solve()<<'\n';
}

J. 辞甲猾扎

题意:树上有一些黑点,你可以选一些未染色的点染白。白点和黑点会一起扩散,每次扩散一条边。
一个点如果仅被白点或黑点扩散则它会变成对应颜色,如果同时被白点和黑点扩散则会变成白色。
求使黑点完全无法扩散最少要染多少个白点。\(n\leq 10^6\)

本质上要求染色的点“占领”了所有与黑点相邻的点(但不需要占领黑点)。
这里“占领”指重合或相邻。

这是经典的“点覆盖点”问题。
树形dp,\(f_{u,0/1/2}\) 表示 \(u\) 自己被染色/被儿子占领/被父亲占领,且子树全部被占领,子树内需染色的最少点数。转移为

\[f_{u,0}=1+\sum_v \min\{f_{v,0},f_{v,1},f_{v,2}\}, 当 $u$ 为黑点时 $f_{u,0} = \infty$,\\ f_{u,1}=1+\sum_v \min\{f_{v,0},f_{v,1}\}, $u$ 需要占领时,至少一个 $v$ 取 $f_{v,0}$,\\ f_{u,2}=1+\sum_v \min\{f_{v,0},f_{v,1}\}, 当 $fa_u$ 为黑点时 $f_{u,2} = \infty.\\ \]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()const int N=1e6+5,inf=1e9;
int n,x,y,f[N],g[N],h[N];
bool a[N],b[N];
vector<int> e[N];
inline void adde(int x,int y){e[x].push_back(y);}
void dfs(int u,int fa){f[u]=1;if(b[u])f[u]=inf;if(b[fa])h[u]=inf;int tmp=inf;for(int v:e[u])if(v^fa){dfs(v,u);int t=min(f[v],g[v]),tt=min(t,h[v]);f[u]+=tt;g[u]+=t,h[u]+=t;tmp=min(tmp,f[v]-g[v]);}if(tmp>0&&a[u])g[u]+=tmp;
}int k;
vector<int> p;
int main(){ios::sync_with_stdio(0);cin.tie(0);cin>>n>>k;p.resize(k);for(int& x:p)cin>>x,b[x]=1;for(int i=1;i<n;++i)cin>>x>>y,adde(x,y),adde(y,x);for(int x:p)for(int y:e[x])if(!b[y])a[y]=1;dfs(1,0);cout<<min(f[1],g[1])<<'\n';
}

D. 摊位分配

题意:有 \(n\) 个社团,\(m\) 个摊位。第 \(i\) 个社团的贡献值为 \(u_i\)。摊位分配方法为在集合 \(\{2^{-j}u_i, 1\leq i\leq n, 0\leq j\leq m-1\}\) 中取出最大的 \(m\) 个值,比较规则为:

  • 优先取 \(u_i\) 大的;
  • 如相等,优先取未分配的;
  • 如还相等,优先取初始 \(u_i\) 大的;
  • 如还相等,优先取 \(i\) 小的。
    然后把摊位分配给相应的社团。问最终每个社团能分到多少摊位。\(n\leq 10^5, m\leq 10^9\)

题目中的方案等价于,一个社团分到一个摊位之后就把它的贡献除 2 再去和剩下的比。

注意到至多 \(n\log w\) 次分配之后,所有社团的贡献值都会落在一个 \([x,2x)\) 的区间。因此它们会依次得到一个摊位然后循环。因此实际上只需算前 \(n\log w\) 次分配即可。

可以用优先队列维护这个过程。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()const int N=1e5+5;int n,m,q,ans[N];
struct node{double u;int id,ans;bool operator < (const node& p)const{if(u!=p.u)return u<p.u;if(!ans)return 0;if(!p.ans)return 1;return id>p.id;}
}a[N];
int id[N];
bool cmp(node a,node b){return a.u>b.u||a.u==b.u&&a.id<b.id;
}
int main(){ios::sync_with_stdio(0);cin.tie(0);cin>>n>>m;if(m>n*30)q=(m-n*30)/n,m-=q*n;for(int i=1;i<=n;++i)cin>>a[i].u,a[i].id=i;sort(a+1,a+n+1,cmp);for(int i=1;i<=n;++i)id[a[i].id]=i,a[i].id=i;priority_queue<node> pq;for(int i=1;i<=n;++i)pq.push(a[i]);for(int i=1;i<=m;++i){node u=pq.top();pq.pop();++u.ans,++ans[u.id],u.u/=2;pq.push(u);}for(int i=1;i<=n;++i)cout<<ans[id[i]]+q<<' ';cout<<'\n';
}

G. Imyourfan

题意:初始有一个仅含 WMX 三个字符的字符串。WM 两人轮流操作,每个人可以找一个不含 X 的子区间删去。若某次操作后

  • 所有 W 都被删去:W 胜;
  • 所有 'M' 都被删去:M 胜;
  • 所有 WM 都被删去:平局。
    求最优决策下的结果。\(|s|\leq 10^5\)

把原串按 X 分隔开,每一段是独立的。

对每个不含 X 的段,单独考虑:

  • 如果 M 的段数比 W 多(等价于首尾都是 M),则 W 必胜;
  • 如果 W 的段数比 M 多(等价于首尾都是 W),则 M 必胜;
  • 如果段数一样多,则谁先开始取谁必胜。

因为 W 先取,所以当 W 必胜段数大于等于 M 必胜段数时,W 占优;反之 M 占优。

当 W 必胜段数等于 M 必胜段数时,有一种特殊情况可以使 M 达到平局:就是取到最后只剩一段,这段是 W 必胜且不是纯 M 段。此时 M 可以一次性全部取完。

M 必胜段数等于 W 必胜段数 +1 时同理。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()void solve(){string s;cin>>s;int n=s.length();int cnt1=0,cnt2=0,cnt3=0,cnt4=0,cnt0=0;for(int i=0,o=0,l=0;i<=n;++i){if(i==n||s[i]=='X'){if(o>0){if(l==1)++cnt1;else ++cnt3;}else if(o<0){if(l==1)++cnt2;else ++cnt4;}else ++cnt0;o=l=0;}else if(s[i]=='W'){if(i==0||s[i-1]!='W')++o,++l;}else if(s[i]=='M'){if(i==0||s[i-1]!='M')--o,++l;}}int d=cnt1+cnt3-cnt2-cnt4;if(d<0)cout<<"Water\n";else if(d>1)cout<<"Menji\n";else if(d==0){if(cnt4>0)cout<<"Draw\n";else cout<<"Water\n";}else if(d==1){if(cnt3>0)cout<<"Draw\n";else cout<<"Menji\n";}
}int main(){ios::sync_with_stdio(0);cin.tie(0);int T;cin>>T;while(T--)solve();
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024CSICN长城杯--Crypto--WriteUp

2024CSICN&长城杯--Crypto--WriteUprasnd task: from Crypto.Util.number import getPrime, bytes_to_long from random import randint import osFLAG = os.getenv("FLAG").encode() flag1 = FLAG[:15] flag2 = FLAG[15:]def crypto1():p = getPrime(1024)q = g…

OS笔记

os cpu执行两种性质的程序内核态程序(管态) 用户态程序内核态执行的特权指令包含:I/O指令 中断指令 存取内存中寄存器指令 程序状态字寄存器变更指令和硬件关联的指令(最底层)包含:时钟管理 中断处理 设备驱动运行比较频繁的指令(最底层的上层)包含:进程管理 内存管理 设…

财务知识-会计做账全套流程

财务知识-会计做账全套流程

druid多数据源配置

AOP实现说明 jump数据源注解 DataSource.javaAOP实现 DataSourceAspect.java数据源常量 DataSourceNames.java动态数据源 DynamicDataSource.java动态数据源config DynamicDataSourceConfig.javaDataSource.java package com.saicmotor.carapp.service.bvalue.manage.common.co…

docker pull拉取镜像超时了 ,可以使用Github Action 构建docker镜像 可以构建arm架构 x86架构镜像

首先要有个GitHub账号把这个项目fork到自己账号底下 地址:https://github.com/wukongdaily/DockerTarBuilder fork了之后进入自己的这个项目底下 点击"Actions" 左边可以选择构建镜像的架构 右边输入要构建的镜像名 输入之后点击 ”Run workflow“ 进行构建 在这里…

44. JavaScript之BOM、DOM

1. BOM 1.1 概念 Browser Object Model是指浏览器对象模型,它使 JavaScript 能与浏览器进行交互。 BOM是浏览器提供的API集合,主要用于处理与浏览器环境相关的任务,如窗口管理、导航、cookie、location等。 1.2 window对象 [1]open() 第一个参数是目标网址,第二个参数可以为…

【嵌入式开发】到底什么是指令集?什么是微架构?他们是什么关系?

一、简述 二、指令集 三、微架构及其与指令集的关系? 四、芯片厂、ARM公司和这些指令集、微架构是什么关系? 五、x86和ARM的竞争!一、简述 CPU的设计遵循图灵机的基本设计思想:任何复杂的运算都可以分解为有限个基本指令的组合来完成。这些基本指令比如加、减、乘、与、或、…

福卫兵-多源异构数据采集与融合应用综合实践

这个项目属于哪个课程 <首页 - 2024数据采集与融合技术实践 - 福州大学 - 班级博客 - 博客园 (cnblogs.com)>这个作业要求在哪里 <综合设计 - 作业 - 2024数据采集与融合技术实践 - 班级博客 - 博客园 (cnblogs.com)>组名、项目简介 <组名:福小兵,项目需求:实…

福卫兵——多源异构数据采集与融合应用综合实践

福州大学多模态网络舆情分析与可视化系统序号 信息类别 内容描述1 这个项目属于哪个课程 数据采集与融合综合实践2 组名、项目简介 组名:福小兵,项目需求:实时舆情监控系统,项目目标:为福州大学提供舆情监控与决策辅助工具,技术路线:使用 Flask 后端、Memfire(PostgreSQ…

SQL优化之《预警事件统计》

在做一件什么事情: 在首页大屏上,可以通过各种维度展示事件统计信息。 sql如下:点击查看代码 SELECTcount( * ) count,camera_code groupName FROMalarm_event WHEREalarm_event.illegal_tag ="24"AND alarm_event.organization_code ="310000110000"AN…

树形dp专项测试1

A. Promises I Cant Keep 题目意为求以每个点为根时的期望得分的最大值,换根DP即可。 式子不太难推,半个小时就出来了。太长了不往这写了。Code#include<bits/stdc++.h> #define ll long long #define il inline #define read(x){\char ch;\int fu=1;\while(!isdigit(c…

测试使用自己编译的WPF框架(本地nuget 包引用)

上一篇博客 本地编译WPF框架源码 - wuty007 - 博客园 说到自己在本地编译WPF 框架源码,并在本地 源码 的 \wpf\artifacts\packages\Debug\NonShipping 路径下打包处了 对应的 nuget包 接下来实操测试一下如何使用这些编译出来的包 一、首先为了方便看到测试的效果,我在WPF源…