当前位置: 首页 > news >正文

GJOI 10.9 题解

1.占卜

题意

在这里插入图片描述
在这里插入图片描述

2≤n≤10182\le n\le 10^{18}2n1018∑n≤1018\sum n\le 10^{18}n10181≤m≤3×1051\le m\le 3\times 10^51m3×105∑m≤3×105\sum m\le 3\times 10^5m3×105

思路

赛时一车人讨论这是异或还是且,这难道不是且吗?

首先当 xix_ixi 出现 444 次即以上,iii 肯定会被满足,只要 00011011 都试一次就能满足。

考虑出现四次的本质:

4
2 2 3 3

比如给两个 222 分配 (a,b)=(1,0)(a,b)=(1,0)(a,b)=(1,0)(0,0)(0,0)(0,0),如果 s3=0s_3=0s3=0 那肯定有一对是猜对了的,因为把 s2=0/1s_2=0/1s2=0/1 都试了一遍。

如果不幸的,s3=1s_3=1s3=1,前面试了两次都错了,那就直接给两个 333 分配 (1,0)(1,0)(1,0)(1,1)(1,1)(1,1) 了,这两对中也肯定有一对是猜对了的,因为把 s4=0/1s_4=0/1s4=0/1 都试了一遍。

即,xxx 出现两次,就能确定 x+1x+1x+1 具体是哪一个数了,只要后面连续,并且还有一个出现 222 次即以上的 x′x'x 来“接应”,就肯定可以构造!尝试验证这个结论:

7
2 2 3 4 5 6 6

同样先给 222 分配 (0,0)(0,0)(0,0)(1,0)(1,0)(1,0),最劣时 s3=1s_3=1s3=1。但是 333 只有 111 个,就没法确定 444 了,不过可以确定给 333 分配 (1,?)(1,?)(1,?)

考虑先看 666。给 666 分配 (0,0)(0,0)(0,0)(0,1)(0,1)(0,1),最劣时 s6=0s_6=0s6=0,那么在 555 时肯定分配 (?,0)(?,0)(?,0)

现在不确定 4,54,54,5。假如 333 那里是 (1,0)(1,0)(1,0),最劣时 s4=1s_4=1s4=1;给 444 分配 (0,0)(0,0)(0,0),最劣时 s5=1s_5=1s5=1,因为已经确定 555 要被分配 (?,0)(?,0)(?,0),所以直接给 555 分配 (1,0)(1,0)(1,0),满足条件结束。

这个过程看似是无穷无尽的,但是因为后面有某个位被确定了(即出现次数 ≥2\ge 22,形成“接应”),于是这个结论被简易验证了。

那就拿一个桶维护出现次数,验证是否出现连续 x,x+1,x+2,...,x′x,x+1,x+2,...,x'x,x+1,x+2,...,x,且 xxxx′x'x 出现次数均为 222 次即以上即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=3e5+9;
ll Q,n,m;
ll a[N];
ll b[N],val[N];
unordered_map<ll,ll>mp;
int main()
{freopen("divination.in","r",stdin);freopen("divination.out","w",stdout);scanf("%lld",&Q);while(Q--){scanf("%lld%lld",&n,&m);for(int i=1;i<=m;i++)scanf("%lld",&a[i]);sort(a+1,a+m+1);bool flag=0;ll tot=1,cnt=0;for(int i=1;i<=m;i++){if(a[i]==a[i+1])tot++;else {if(tot>=4)flag=1;b[++cnt]=tot;val[cnt]=a[i];tot=1;}}if(flag){puts("Yes");continue;}for(int l=1;l<=cnt;){ll r=l;if(b[l]>=2){while(r<=cnt&&val[r]+1==val[r+1]){r++;//b[r]>0,可以接续 if(b[r]>=2){flag=1;break;}}}if(flag)break;l=r+1;}if(flag)puts("Yes");else puts("No");}return 0;
}

2.CF2006C Eri and Expanded Sets

题意

在这里插入图片描述
1≤n≤2×1051\le n\le 2\times 10^51n2×105∑n≤2×105\sum n\le 2\times 10^5n2×105ai∈[1,1018]a_i\in[1,10^{18}]ai[1,1018]

CF2006C 数据:1≤n≤4×1051\le n\le 4\times 10^51n4×105a∈[1,109]a\in[1,10^9]a[1,109]

两个数据范围做法本质相同。

思路

钦定 ci=ai+1−ai,m=n−1c_i=a_{i+1}-a_i,m=n-1ci=ai+1ai,m=n1,记 g=gcd⁡i=lr−1cig=\displaystyle\gcd_{i=l}^{r-1} c_ig=i=lgcdr1ci,定义 n2(x)n2(x)n2(x) 操作表示,对 xxx 一直除以 222 直到不能整除。

整道题围绕着一个结论:

  • ggg222 的幂或者 111,区间 [l,r][l,r][l,r] 的数就可以被削成 al,al+1,...,ara_l,a_l+1,...,a_ral,al+1,...,ar

因为一直 x+y2=x+y−x2\frac{x+y}{2}=x+\frac{y-x}{2}2x+y=x+2yx,可以把 ci=y−xc_i=y-xci=yx222 的因子消耗掉。而如果出现其它质因子就肯定消不掉,导致最后处在公差为 n2(g)n2(g)n2(g) 的等差数列。

题目问区间个数,考虑固定一个左端点,计算有多少右端点 rrr。我们只需要找到最小的 r0≥lr_0\ge lr0l,使得 n2(g)=n2(gcd⁡i=lr0−1ci)=1n2(g)=n2\left(\displaystyle\gcd_{i=l}^{r_0-1} c_i\right)=1n2(g)=n2(i=lgcdr01ci)=1,因为 r0r_0r0 往后再和 ggggcd⁡\gcdgcd 必然不大于 ggg,即依然是 111。同时显然的,gcd⁡\gcdgcdl∼nl\sim nln 是单调递减的,于是 r0r_0r0 的位置是可二分的。

bool check(ll nl,ll mid)//区间gcd(已经进行剥离2因子操作)
{return query(nl,mid)==1;
}
...
for(int i=1;i<=m;i++)
{ll l=i,r=m,j=m;bool flag=0;//是否有合法的右界出现while(l<=r){ll mid=(l+r)>>1;if(check(i,mid))j=mid,r=mid-1,flag=1;//相等不能当做存在多个,只能算作1个 else l=mid+1;}if(flag)ans+=n-j;//j=r0-1
}

那么我们需要快速获取区间 gcd⁡\gcdgcd,因为可以区间合并,于是可以使用线段树或者 ST 表,又因为不带修于是 ST 表了。注意 ST 表的下标是间隔编号,不是元素编号。左端点 lllala_lal 右边的间隔 clc_lcl,上面二分得到 jjj 的其实是 r0−1r_0-1r01

ll no2(ll x)//可以直接x/lowbit(x)
{if(x==0)return 0;while(x%2==0)x/=2;return x;
}
ll fgcd[N][M],lg2[N];
void init()
{lg2[1]=0;lg2[2]=1;for(int i=3;i<N;i++)lg2[i]=lg2[i/2]+1;
}
void getGCD()
{for(int i=1;i<=m;i++)fgcd[i][0]=no2(c[i]);//提前剥离2因子不影响单调性,依然可以合并 for(int j=1;j<=lg2[m];j++)for(int i=1;i+(1<<j)-1<=m;i++)fgcd[i][j]=__gcd(fgcd[i][j-1],fgcd[i+(1<<(j-1))][j-1]);
}
ll query(ll l,ll r)
{ll s=lg2[r-l+1];return __gcd(fgcd[l][s],fgcd[r-(1<<s)+1][s]);
}

但有个点要注意,如果遇到相邻的数,会出现 ci=0c_i=0ci=0,众所周知 C++ 的 __gcd(x,y) 遇到其中一个数是 x=0x=0x=0 是并不会返回 000 而是返回 yyy,所以遇到 lll 开始一堆 ci=0c_i=0ci=0、后面又有数的就不单调了。但是二分 check 的条件是区间 gcd⁡=1\gcd=1gcd=1,一串相同的数出现(出现 gcd⁡=0\gcd=0gcd=0 只会缩进左界)不影响答案。于是相同的数找到连续若干个 ci=0c_i=0ci=0 再算进贡献。

二分答案那里 O(nlog⁡n)O(n\log n)O(nlogn),预处理 ST 表因为 gcd⁡\gcdgcd 也带个 log⁡\loglog,于是总体是 O(nlog⁡2n)O(n\log^2 n)O(nlog2n) 的。

别忘了只加一个数亦可以。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=4e5+9,M=20,inf=3e14;
ll Q,n,m;
ll a[N],c[N];
ll no2(ll x)
{if(x==0)return 0;while(x%2==0)x/=2;return x;
}
ll cal(ll len)
{return len*(len+1)/2;
}
ll fgcd[N][M],lg2[N];
void init()
{lg2[1]=0;lg2[2]=1;for(int i=3;i<N;i++)lg2[i]=lg2[i/2]+1;
}
void getGCD()
{for(int i=1;i<=m;i++)fgcd[i][0]=no2(c[i]);//提前剥离2因子不影响单调性,依然可以合并 for(int j=1;j<=lg2[m];j++)for(int i=1;i+(1<<j)-1<=m;i++)fgcd[i][j]=__gcd(fgcd[i][j-1],fgcd[i+(1<<(j-1))][j-1]);
}
ll query(ll l,ll r)
{ll s=lg2[r-l+1];return __gcd(fgcd[l][s],fgcd[r-(1<<s)+1][s]);
}
bool check(ll nl,ll mid)
{return query(nl,mid)==1;
}
int main()
{freopen("set.in","r",stdin);freopen("set.out","w",stdout);init();scanf("%lld",&Q);while(Q--){scanf("%lld",&n);for(int i=1;i<=n;i++){scanf("%lld",&a[i]);if(i>1)c[i-1]=abs(a[i]-a[i-1]);}m=n-1;getGCD();ll ans=0,l0=0;c[n]=-1;for(int i=1;i<=n;i++){if(c[i]==0)l0++;else {ans+=cal(l0);l0=0;}}for(int i=1;i<=m;i++){ll l=i,r=m,j=m;bool flag=0;while(l<=r){ll mid=(l+r)>>1;if(check(i,mid))j=mid,r=mid-1,flag=1;//相等不能当做存在多个,只能算作1个 else l=mid+1;}if(flag)ans+=n-j;}printf("%lld\n",ans+n);//记得加上单个}return 0;
}

3.AT_arc178_d Delete Range Mex

题意

给定一个正整数 NNN 和一个长度为 MMM 的非负整数序列 AAAAAA 的所有元素都 ∈[0,N)\in[0,N)[0,N),并且互不相同。

请计算有多少个排列 BBB 满足以下条件,并输出答案对 998244353998244353998244353 取模后的结果。将排列 BBB 通过任意次数以下操作变为 AAA

  • 选择满足 1≤l≤r≤∣B∣1\leq l\leq r\leq |B|1lrBl,rl,rl,r,如果 mex({Bl,Bl+1,…,Br})\mathrm{mex}(\{B_{l},B_{l+1},\dots,B_{r}\})mex({Bl,Bl+1,,Br})BBB 中出现,则将其从 BBB 中删除。
  • BBB 的所有元素都 ∈[0,N)\in[0,N)[0,N)

mex(X)\mathrm{mex}(X)mex(X) 的定义如下:对于由非负整数组成的有限集合 XXXmex(X)\mathrm{mex}(X)mex(X) 是满足 x∉Xx\notin Xx/X 的最小非负整数 xxx

1≤M≤N≤5001\le M\le N\le 5001MN500Ai∈[0,N)A_i\in[0,N)Ai[0,N)

南海云课堂题意:Ai∈[1,n]A_i\in[1,n]Ai[1,n],将 AiA_iAi 全部 −1-11 就是相同题意。

思路

思路和实现参考这篇博客,有点贺了呜呜呜。

在区间 [l,r][l,r][l,r] 成功删掉 x=mexl,rx=\text{mex}_{l,r}x=mexl,r,需要满足,[l,r][l,r][l,r] 包含 0∼x−10\sim x-10x1 的数且不包含 xxx

原排列 BBB 删掉一些数得到 AAA,令删除数形成的有序序列为 DDD。删除的数字按顺序来看必须是从大到小的,否则 xxx 不能成为 mex\text{mex}mex

同时在原序列中,比 xxx 小的数都在某个区间 [l,r][l,r][l,r] 中,于是区间 [l,r][l,r][l,r] 要么在 xxx 左边要么右边。

考虑倒着插回去,从小到大插入 AAA 得到若干合法的 BBB∣A∣=M|A|=MA=M 于是有 M+1M+1M+1 个间隔可以插数,一个间隔可以插若干数。设 fx,l,rf_{x,l,r}fx,l,r 表示插入了 0∼x0\sim x0x,枚举占用了 [l,r][l,r][l,r] 区间((l,r)(l,r)(l,r) 空隙),剩余 [1,l]∪[r,n][1,l]\cup[r,n][1,l][r,n] 空隙可以插入数的方案数。

x∈Ax\in AxA,记 xxx 的出现位置为 posxpos_xposx,出现在 posx∼posx+1pos_x\sim pos_x+1posxposx+1 区间当中,以后要填的 x′>xx'>xx>x 就不能插在同一个地方了。于是:
fx,min⁡(posx,l),max⁡(posx+1,r)←fx−1,l,rf_{x,\min(pos_x,l),\max(pos_x+1,r)}\leftarrow f_{x-1,l,r}fx,min(posx,l),max(posx+1,r)fx1,l,r

xxx 没有在 AAA 中出现过,就插在比它小的数的左侧或者右侧,即分别枚举左右端点 fx,l,r←∑i=lrfx−1,i,rf_{x,l,r}\leftarrow \sum_{i=l}^rf_{x-1,i,r}fx,l,ri=lrfx1,i,rfx,l,r←∑i=lrfx−1,l,if_{x,l,r}\leftarrow \sum_{i=l}^rf_{x-1,l,i}fx,l,ri=lrfx1,l,i。这个可以前缀和优化,枚举左右端点的时候就能做完。

要特别讨论 000,若 000 存在当然 f0,posx,posx+1=1f_{0,pos_x,pos_x+1}=1f0,posx,posx+1=1;否则 000 不存在,随便选一个区间,都能把 xxx 删掉,此时 f0,i,i=1f_{0,i,i}=1f0,i,i=1。这就是初始化。

最后答案就是 fn−1,1,m+1f_{n-1,1,m+1}fn1,1,m+1

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=502,mod=998244353;
ll n,m;
ll a[N];
ll pos[N];
ll f[N][N][N];
int main()
{
//	freopen("heritage.in","r",stdin);
//	freopen("heritage.out","w",stdout);scanf("%lld%lld",&n,&m);for(int i=1;i<=m;i++){scanf("%lld",&a[i]);pos[a[i]]=i;}if(!pos[0]){for(int i=1;i<=m+1;i++)f[i][i][0]=1;}else f[pos[0]][pos[0]+1][0]=1;for(int x=1;x<n;x++){if(!pos[x]){for(int j=1;j<=m+1;j++){ll s=0;for(int i=j;i>=1;i--){s=(s+f[i][j][x-1])%mod;f[i][j][x]=(f[i][j][x]+s)%mod; }}for(int i=1;i<=m+1;i++){ll s=0;for(int j=i;j<=m+1;j++){s=(s+f[i][j][x-1])%mod;f[i][j][x]=(f[i][j][x]+s)%mod;}}}else {for(ll i=1;i<=m+1;i++){for(ll j=i;j<=m+1;j++){ll l=min(pos[x],i),r=max(pos[x]+1,j);f[l][r][x]=(f[l][r][x]+f[i][j][x-1])%mod;}}}}printf("%lld",f[1][m+1][n-1]);return 0;
}

南海云课堂题面敬请自行修改。

4.AT_arc174_f Final Stage

http://www.dtcms.com/a/469477.html

相关文章:

  • 如何设计一个架构良好的前端请求库?
  • 精灵图(雪碧图)的生成和使用
  • Web 开发 27
  • 网站制作主要公司学校网站开发系统的背景
  • Linux小课堂: 目录操作命令深度解析(LS 与 CD 命令)
  • 面向财经新闻的文本挖掘系统设计与实现(论文)
  • 【Redis-cli操作数据类型】Redis八大数据类型详解:从redis-cli操作到场景落地
  • linux安装海量数据库和操作
  • Redis分片+Sentinel熔断设计TP99控制在15ms内
  • 山海关城乡建设局网站佛山网络科技公司有哪些
  • 我的算法模板1(快速幂、逆元、组合数)
  • 八股-2025.10.11
  • 图片上传网站变形的处理旅游网站建设的概念
  • 集团培训网站建设注册公司需要什么条件和手续
  • Spark RDD详解 —— RDD特性、lineage、缓存、checkpoint、依赖关系
  • 玩转Docker系列专栏大纲
  • 网络攻防技术:信息收集技术
  • spark on hive 还是 hive on spark?
  • 搞懂数据通信不用愁!网络基础 + 参考模型 + VRP 配置,一篇全搞定
  • 解决MacOS上CLion调试的时候容器的值显示为0的问题
  • Docker快速入门——第一章Docker入门
  • 建站助手官网淘宝seo具体优化方法
  • 邯郸网站建设哪儿好网站建设参考文献英文书籍
  • STM32 串口收发数据-中断的方式
  • k8s ingress-nginx 学习
  • 【含文档+PPT+源码】基于springboot的旅游路线推荐系统的设计与实现
  • 嘉兴seo网站优化竞价托管的注意事项
  • K8S 概念、安装与核心工作机制详解
  • 做网站需要公司有哪些网站最新点击量排名
  • VUE 开发实例 一则