终于进前一千了。

A - Shuffled Equation

人话:给定三个数 \(a,b,c\),判断是否存在两个数乘积为第三个数。

数很小,if 判断一下,long long 也不用开。

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int a,b,c;
int main(){
cin>>a>>b>>c;
if(a*b==c)cout<<"Yes"<<endl;
else if(b*c==a)cout<<"Yes"<<endl;
else if(c*a==b)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}

时间复杂度 \(O(1)\)。

B - Who is Missing?

注意到值域很小,我们开一个桶。如果 \(i\) 出现过,则 \(f_i\) 为 \(1\),反之为 \(0\)。

然后按照 \(1\sim n\) 的顺序检查那个桶里没数就行。

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int n,m,x,t[1005],cnt;
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++)cin>>x,t[x]++;
for(int i=1;i<=n;i++)if(!t[i])cnt++;
cout<<cnt<<endl;
for(int i=1;i<=n;i++)if(!t[i])cout<<i<<" ";
return 0;
}

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

C - Bib

挺绕的。

每个人有三个属性,编号,牌子(也就是 \(p_i\)),看的人的编号(也就是 \(q_i\))。

假设 \(s_i\) 表示牌子上的数位 \(i\) 的人的编号。这个可以预处理建立映射关系。

那么根据定义,牌子为 \(i\) 的人编号为 \(s_i\),看的人的编号为 \(q_{s_i}\),看的人挂的牌子为 \(p_{q_{s_i}}\)。

主要是搞清楚编号,牌子,看的人之间的关系即可。

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N=3e5+10;
int n,p[N],q[N],s[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",q+i);
}
for(int i=1;i<=n;i++){
scanf("%d",s+i);
p[s[i]]=i;
}
for(int i=1;i<=n;i++){
printf("%d ",s[q[p[i]]]);
}
return 0;
}

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

D - Doubles

咋还卡人精度呢?

先思考暴力,枚举两个骰子 \(i,j\),枚举摇出来的数 \(x\),则答案就是:

\[\sum_{x=1}^{\infty}\dfrac{cnt_{i,x}}{k_i}\times \dfrac{cnt_{j,x}}{k_j}
\]
\[\dfrac{\sum\limits_{x=1}^{\infty}cnt_{i,x}\times cnt_{j,x}}{k_ik_j}
\]

\(cnt_{i,j}\) 表示骰子 \(i\) 有多少个面是 \(j\),上面的式子根据乘法原理和加法原理易得。

暴力会超时,注意值域很小,我们先枚举 \(i\),然后开一个桶 \(t_j\) 表示骰子 \(i\) 有多少个面为 \(j\)。

接着我们枚举每一个 \(j<i\),分别计算 \(i,j\) 的答案,具体做法是遍历 \(j\) 骰子的每一个面 \(x\),然后让答案 \(ans\) 加上 \(t_x\)。最后 \(\frac{ans}{k_ik_j}\)。

枚举 \(i\) 是 \(O(n)\) 的,枚举每一个骰子 \(i\) 的面是 \(K_i\),枚举 \(j\),枚举 \(j\) 骰子的每一个面可以看成一个整体,是 \(O(S-K_i)\) 的,其中 \(S=\sum K_i\),意思是最多会将除了骰子 \(i\) 以外其他所有骰子的所有面都遍历一遍。

容易发现后两步合起来是 \(O(S)\)。这样做复杂度均摊下来是正确的。

点击查看代码
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int N=1e5+10;
vector<int>v[105];
int n;
long long k[105],cnt[N];
long double res,ans;
long double fmax(long double a,long double b){
return a<b?b:a;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",k+i);
for(int j=1,x;j<=k[i];j++){
scanf("%d",&x);
v[i].push_back(x);
}
}
for(int i=2;i<=n;i++){
for(auto u:v[i])cnt[u]++;
for(int j=1;j<i;j++){
res=0;
for(auto u:v[j])res=(double)(res+cnt[u]);
res=(long double)(res/(k[i]*k[j]));
ans=max(ans,res);
}
for(auto u:v[i])cnt[u]--;
}
printf("%.12LF\n",ans);
return 0;
}

时间复杂度 \(O(nS)\)。

E - Cables and Servers

小清新题。

注意到 \(M\ge N-1\),也就是说无论如何我们也可以给所有边的两个端点重新编号,让他联通。

我们先把原图建出来,这样的图是若干个不连通的图。在原图中,有一些边是无关紧要的,去掉这一条边对原图联通性没有影响。我们可以用这些边来连接其他的联通块。

我们思考这样一个过程:划分联通块,然后找出每个联通块有多少个无用的边,统计当前那个联通块 \(u\) 无用边最多,那个联通块 \(v\) 无用边次多,将 \(u\) 内的一条无用边的一个端点改到 \(v\) 上的端点,此时 \(u,v\) 就被合并了,\(v\) 的无用边也变成了 \(u\) 的无用边。因为 \(M\ge N-1\),所以除了这个图仅剩一个联通块的情况,无论何时都有无用边

容易发现,此时 \(u,v\) 合并后的联通块又成为了无用边最多的联通块,假设有 \(k\) 个联通块,我们按照每个联通块内部无用边多少排序,然后依次将 \(2\sim k\) 的联通块和 \(1\) 合并,这个算法就是正确的,容易发现,这样的操作此时为 \(k-1\)。

考虑构造方案,我们把每个联通块排好序后,将每个联通块内的无用边按照同样顺序放进数组里,然后从前往后一条一条边的用即可。

点击查看代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int N=2e5+10;
int n,m,a[N],b[N],f[N],rt[N],k,rest[N],p,mk[N];
vector<int>vec[N];
int found(int x){
return f[x]==x?x:f[x]=found(f[x]);
}
bool cmp(int a,int b){
return vec[a].size()>vec[b].size();
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++){
scanf("%d %d",a+i,b+i);
int u=found(a[i]);
int v=found(b[i]);
if(u!=v)f[u]=v;
else mk[i]=1;
}
for(int i=1;i<=m;i++)if(mk[i])vec[found(a[i])].push_back(i);
for(int i=1;i<=n;i++)if(found(i)==i)rt[++k]=i;
printf("%d\n",k-1);
sort(rt+1,rt+1+k,cmp);
for(int i=1;i<=k;i++)for(auto j:vec[rt[i]])rest[++p]=j;
for(int i=2;i<=k;i++){
printf("%d %d %d\n",rest[i-1],a[rest[i-1]],rt[i]);
}
return 0;
}

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

F - Insert

平衡树板子,蚌埠住了。

考虑无旋 treap(FHQ treap),每个节点上维护一个权值,和子树的大小,插入第 \(i\) 个数时,假设这个数排名为 \(k\)。split 时,将平衡树分成两颗大小分别为 \(k-1\) 和 \(i-k\) 两颗平衡树,merge 时把新建的节点夹在中间合并即可,时间复杂度 \(O(n\log n)\)。

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int N=5e5+10;
int tot,root,n;
struct node{
int l,r,size,dat,val;
}a[N];
int New(int s){
a[++tot].val=s;
a[tot].size=1;
a[tot].dat=rand();
return tot;
}
void update(int p){
a[p].size=a[a[p].l].size+a[a[p].r].size+1;
}
void split(int p,int k,int &x,int &y){
if(!p)return x=y=0,void();
else if(a[a[p].l].size+1<=k)split(a[p].r,k-a[a[p].l].size-1,a[x=p].r,y);
else split(a[p].l,k,x,a[y=p].l);
update(p);
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(a[x].dat>a[y].dat)return a[x].r=merge(a[x].r,y),update(x),x;
else return a[y].l=merge(x,a[y].l),update(y),y;
}
void insert(int s,int k){
int x=0,y=0;
split(root,k-1,x,y);
root=merge(merge(x,New(s)),y);
}
void print(int p){
if(!p)return;
print(a[p].l);
printf("%d ",a[p].val);
print(a[p].r);
return;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int p;
scanf("%d",&p);
insert(i,p);
}
print(root);
return 0;
}

多的可以去看平衡树模板。

G - Fine Triplets

好好好,都会 FFT/NTT 是吧。

首先 \(B-A=C-B\) 可以写作 \(2B=A+C\),所以我们只需要求出有多少个数对 \((A,C)\) 和为 \(2B\)。

我们不妨开一个桶 \(t\),\(t_x\) 表示 \(S\) 中 \(x\) 的出现次数。记 \(m=2B\),上面说的这个问题答案即为 \(\sum_{i=1}^{m-1}t_it_{m-i}\) 的一半(因为求得是无序数对)。

这个玩意不就是一个卷积吗,FFT/NTT 可以 \(O(n\log n)\) 求出来。

?这不是卷积模板吗。

好吧,我不会卷积。。。

随机推荐

  1. Robot Framework原生库的编辑与应用

    RF有一些操作指令不存在,需要自己添加方法,比如selenium里有click_and_hold指令(鼠标保持点击状态)而RF内没有.所以需要在库文件里加入这个方法 C:\Python27\Lib\s ...

  2. 几种JAVA表达式语言计算工具

    测试表达式工具分类 这里测试了几种方式,MS excel,Spring SEPL,MVEL,Google aviator import com.googlecode.aviator.AviatorEv ...

  3. DPDI(Dispatch PDI)kettle调度管理平台之实操演练第003讲-数据通途:客户端连接SQL Server的完美攻略

    SQL Server简介 基本概念 SQL Server是由微软公司开发的关系型数据库管理系统.它基于SQL(Structured Query Language,结构化查询语言)来管理和操作数据.SQ ...

  4. 用c#从头写一个AI agent,实现企业内部自然语言数据统计分析

    1.本文目的 不借助任何框架,使用c#写一个agent,实现调用阿里千问大模型完成预定任务.同时完成一个可扩展的agent框架雏形. 2.预期读者 本文假设读者已经了解了一些基本概念,例如AI,fun ...

  5. hadoop问题解决(七)日志/重启/开机自启动

    6.1hadoop日志 Master节点 Slave节点 6.2 hadoop排错 (待补充) 6.3 spark 6.4 zookeeper 6.5 hive 6.6 kafka 7重启命令 7.1 ...

  6. AUTOFAC学习DEMO2-——ContainerBuilder注册三种方式、反射注册

    注册组件 通过容器构造器ContainerBuilder注册组件的三种方式: 通过类型反射注册 通过现存实例注册(实现对象的实例) lambda表达式注册(通过可实例化对象的匿名函数注册) 每个组件可 ...

  7. 331K star!福利来啦,搞定所有API开发需求,这个开源神器绝了!

    嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 「public-apis」是GitHub上最全面的免费API资源库,收录了涵盖商业.娱乐.教 ...

  8. 【HUST】网安|编译原理实验|实验四攻略

    [实验代码及报告地址:Gitee传送门](已关闭传送大门,原因是抄袭过多,如需参考,请直接看博客,虽然下一届内容会变了) 不擅长写报告昂,很多地方能省全省了. 助力来年编译原理加大难度!(hhh) M ...

  9. Python 深拷贝 vs 浅拷贝

    在一些业务场景中, 有时候我们需要复制一个对象, 但是又不想对原来的对象产生影响, 就想搞个 副本 来为所欲为地操作嘛. 但是呢, 在 Python中呢, 又不能通过 赋值 的方式达到效果, 为啥呢? ...

  10. HarmonyOS数据防泄漏服务(DLP)开发实战

    系统级数据防护的核心能力解析 在企业级文档管理.教育课件分发.金融合同处理等场景中,数据泄露风险贯穿文件生命周期.HarmonyOS提供的数据防泄漏服务(DLP),通过沙箱隔离.端云协同认证.细粒度权 ...