JXOI2018简要题解

T1 排序问题

题意

九条可怜是一个热爱思考的女孩子。

九条可怜最近正在研究各种排序的性质,她发现了一种很有趣的排序方法: Gobo sort !

Gobo sort 的算法描述大致如下:

  1. 假设我们要对一个大小为 \(n\) 的数列 \(a\) 排序。
  2. 等概率随机生成一个大小为 \(n\) 的排列 \(p\) 。
  3. 构造一个大小为 \(n\) 的数列 \(b\) 满足 \(b_i=a_{p_i}\) ,检查 \(b\) 是否有序,如果 \(b\) 已经有序了就结束算法,并返回 \(b\) ,不然返回步骤 \(2\) 。

显然这个算法的期望时间复杂度是 \(O(n\times n!)\) 的,但是九条可怜惊奇的发现,利用量子的神奇性质,在量子系统中,可以把这个算法的时间复杂度优化到线性。

九条可怜对这个排序算法进行了进一步研究,她发现如果一个序列满足一些性质,那么 Gobo sort 会很快计算出正确的结果。为了量化这个速度,她定义 Gobo sort 的执行轮数是步骤 \(2\) 的执行次数。

于是她就想到了这么一个问题:

现在有一个长度为 \(n\) 的序列 \(x\) ,九条可怜会在这个序列后面加入 \(m\) 个元素,每个元素是 \([l,r]\) 内的正整数。

她希望新的长度为 \(n+m\) 的序列执行 Gobo sort 的期望执行轮数尽量的多。她希望得到这个最多的期望轮数。

九条可怜很聪明,她很快就算出了答案,她希望和你核对一下,由于这个期望轮数实在是太大了,于是她只要求你输出对 \(998244353\) 取模的结果。

对于 \(30\%\) 的数据, \(T\leq 10\) , \(n,m,l,r\leq 8\)。

对于 \(50\%\) 的数据, \(T\leq 300,n,m,l,r,a_i\leq 300\) 。

对于 \(60\%\) 的数据, \(\sum{r-l+1}\leq 10^7\) 。

对于 \(70\%\) 的数据, \(\sum{n} \leq 2\times 10^5\) 。

对于 \(90\%\) 的数据,\(m\leq 2\times 10^5\)。

对于 \(100\%\) 的数据, \(T\leq 10^5,n\leq 2\times 10^5,m\leq 10^7,1\leq l\leq r\leq 10^9\) 。

对于 \(100\%\) 的数据, \(1\leq a_i\leq 10^9,\sum{n}\leq 2\times 10^6\) 。

题解

一道不错的签到题。

首先如果每个数都不同,画一画可以知道,有且只有唯一的一种排列是满足条件的,此时需要\(n!\)次。

但是有数相同,那么我们可以强制他们有大小关系、每一种大小关系对应一种排列。如果相同的数个数分别是\(a_1,a_2...a_k\),则答案为\(\frac{n!}{a_1!a_2!a_3!...a_k!}\)

考虑怎么样加数会使得答案最大:肯定越平均越大(优先加个数少的数字,因为乘的分母小)。于是就维护一个类似阶梯的东西贪心地加就好了。

代码

#include<iostream>
#include<algorithm>
using namespace std;
const int mod=998244353,N=2e5+10;
int n,m,l,r,jc[11000000],a[N],b[N],c[N],t[N];
int ksm(int x,int k)
{
int s=1;for(;k;k>>=1,x=1ll*x*x%mod)
if(k&1) s=1ll*s*x%mod;return s;
}
void Work()
{
scanf("%d%d%d%d",&n,&m,&l,&r);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
int ans=jc[n+m],t1=0,t2=0,top=0;
for(int i=1;i<=n;i++)
if(a[i]>=l&&a[i]<=r) b[++t1]=a[i];
else c[++t2]=a[i];
b[t1+1]=c[t2+1]=0;
for(int i=2,res=1;i<=t2+1;i++)
if(c[i]!=c[i-1]) ans=1ll*ans*ksm(jc[res],mod-2)%mod,res=1;
else res++;
for(int i=2,res=1;i<=t1+1;i++)
if(b[i]!=b[i-1]) t[++top]=res,res=1;
else res++;
sort(t+1,t+top+1);
int s=r-l+1-top,nw=0,i=1;
for(;i<=top;i++)
if(1ll*s*(t[i]-nw)<=m)
m-=1ll*s*(t[i]-nw),nw=t[i],s++;
else break;
nw+=m/s;m%=s;
ans=1ll*ans*ksm(ksm(jc[nw+1],mod-2),m)%mod;
ans=1ll*ans*ksm(ksm(jc[nw],mod-2),s-m)%mod;
for(;i<=top;i++) ans=1ll*ans*ksm(jc[t[i]],mod-2)%mod;
printf("%d\n",ans);
}
int main()
{
int T;cin>>T;jc[0]=1;
for(int i=1;i<=1e7+1e6;i++) jc[i]=1ll*jc[i-1]*i%mod;
while(T--) Work();
}

T2 游戏

题意

九条可怜是一个富有的女孩子。她长大以后创业了,开了一个公司。

但是管理公司是一个很累人的活,员工们经常背着可怜偷懒,可怜需要时不时对办公室进行检查。

可怜公司有 \(n\) 个办公室,办公室编号是 \(l\sim l+n-1\) ,可怜会事先制定一个顺序,按照这个顺序依次检查办公室。一开始的时候,所有办公室的员工都在偷懒,当她检查完编号是 \(i\) 的办公室时候,这个办公室的员工会认真工作,并且这个办公室的员工通知所有办公室编号是 \(i\) 的倍数的办公室,通知他们老板来了,让他们认真工作。因此,可怜检查完第 \(i\) 个办公室的时候,所有编号是 \(i\) 的倍数(包括 \(i\) )的办公室的员工会认真工作。

可怜发现了员工们通风报信的行为,她发现,对于每种不同的顺序 \(p\) ,都存在一个最小的 \(t(p)\) ,使得可怜按照这个顺序检查完前 \(t(p)\) 个办公室之后,所有的办公室都会开始认真工作。她把这个 \(t(p)\) 定义为 \(p\) 的检查时间。

可怜想知道所有 \(t(p)\) 的和。

但是这个结果可能很大,她想知道和对 \(10^9+7\) 取模后的结果。

对于 \(20\%\) 的数据,\(r-l+1\leq 8\)。

对于另 \(10\%\) 的数据,\(l=1\)。

对于另 \(10\%\) 的数据,\(l=2\)。

对于另 \(30\%\) 的数据,\(l\leq 200\)。

对于 \(100\%\) 的数据,\(1\leq l\leq r\leq 10^7\)。

题解

一道简单的组合计数问题。

如果把倍数关系画成一张拓扑图的话,那么当且仅当入度为0的点都被选了,检查结束。

设一共有k个入度为0的点,考虑选多少次能够选全,答案就是

\[\sum_{i=k-1}^{n-1}(i+1)C_{i}^{k-1}k!(n-k)!
\]

含义是在前\(i\)次中选了\(k-1\)个,在第\(i+1\)次中选了剩下的那一个。贡献是\(i+1\),在前\(i\)次中选出\(k-1\)次决策用来选必选点,把每一种决策是否选必选点分配好后、只需要把必选点和非必选点排列上去就是方案了,为\(k!(n-k)!\)。

在找入度为0的点是用线性筛,找到自己在\([l,r]\)且为质数或最大因数不在\([l,r]\)的数。

代码

#include<iostream>
using namespace std;
const int N=1e7+10,mod=1e9+7;
int l,r,n,Ans,cnt,ispri[N],pri[N],jc[N],inv[N],tot;
int ksm(int x,int k)
{
int s=1;for(;k;k>>=1,x=1ll*x*x%mod)
if(k&1) s=1ll*s*x%mod;return s;
}
void Pre()
{
ispri[1]=pri[1]=1;
if(l==1) {cnt=1;return;}
for(int i=2;i<=r;i++)
{
if(!ispri[i]) pri[++tot]=i,cnt+=(i>=l);
for(int j=1;j<=tot&&i*pri[j]<=r;j++)
{
ispri[i*pri[j]]=1;
if(i<l&&i*pri[j]>=l) cnt++;
if(i%pri[j]==0) break;
}
}
}
int main()
{
cin>>l>>r;n=r-l+1;Pre();jc[0]=inv[0]=1;
for(int i=1;i<=r;i++) jc[i]=1ll*jc[i-1]*i%mod;
inv[r]=ksm(jc[r],mod-2);
for(int i=r-1;i>=1;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
for(int i=cnt-1;i<=n-1;i++)
(Ans+=1ll*jc[i]*inv[i-cnt+1]%mod*(i+1)%mod)%=mod;
Ans=1ll*Ans*cnt%mod*jc[n-cnt]%mod;
cout<<Ans<<endl;
}

T3 守卫

题意

九条可怜是一个热爱运动的女孩子。

这一天她去爬山,她的父亲为了她的安全,雇了一些保镖,让他们固定地呆在在山的某些位置,来实时监视九条可怜,从而保护她。

具体来说,一座山可以描述为一条折线,折线的下方是岩石。这条折线有 \(n\) 个折点,每个折点上有一个亭子,第 \(i\) 个折点的坐标是 \((i,h_i)\) 。九条可怜只可能会在亭子处玩耍,那些保镖也只会在亭子处监视可怜。

由于技术方面的原因,一个保镖只能监视所有他能看得到的,横坐标不超过他所在位置的亭子。我们称一个保镖能看到一个亭子 \(p\) ,当且仅当他所在的亭子 \(q\) 和 \(p\) 的连线不经过任何一块岩石。特别地,如果这条连线恰好经过了除了 \(p,q\) 以外的亭子,那么我们认为保镖看不到可怜。

雇佣保镖是一件很费钱的事情,可怜的父亲希望保镖越少越好。

可怜的父亲还希望得到详尽的雇佣保镖的方案,他知道有些亭子可能正在维修,他想对所有的 \(1\leq l\leq r\leq n\) 计算:如果事先已知了只有区间 \([l,r]\) 的亭子可以用来玩耍(和监视),那么最少需要多少个保镖,才能让 \([l,r]\) 中的每一个亭子都被监视到。

可怜的父亲已经得到了一个结果,他希望和你核实他的结果是否正确。

对于 \(30\%\) 的数据, \(n\leq 20\) 。

对于 \(70\%\) 的数据, \(n\leq 500\) 。

对于 \(100\%\) 的数据, \(n\leq 5000\) 。

对于 \(100\%\) 的数据, \(1\leq h_i\leq 10^9\) 。

题解

略有难度的DP。

首先可以维护斜率最值来得到两点间的可见关系。(一开始以为可见区域一定是一段区间,搞了好久的贪心结果错了,Hack:5 1 4 5)

然后设\(f[l][r]\)表示这个区间的最少关键点数,那么一定要在\(r\)处放置一个,再依次找\(r\)看不到的极大区间\([l1,r1]\),考虑在\(r1,r1+1\)中选一个点作为关键点就好了。

一个需要解释的地方就是为什么\([r1+2,r]\)都看不到\([l1,r1]\):因为\(r\)看得到\(r1+1\)和\(r1+2\),所以\(r\)和\(r1+2\)连线的夹角要大一些、在\(r\)和\(r1+1\)连线下方;如果\(r1+2\)看得到\(r1\)的话,则\(r1+2\)和\(r1+1\)的连线的夹角比\(r1+2\)和\(r1\)的大。夹角均为x正半轴出发的有向角,如此一画发现矛盾,\(r1+2\)看不到\(r1\)。

代码很简单,固定一个\(r\),从后往前扫\(l\)。

代码

#include<iostream>
using namespace std;
const int N=5100;
int n,h[N],f[N][N],see[N][N],ans;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>h[i];
for(int i=1,l=0;i<=n;i++,l=i-1)
for(double mn=1e9;l>=1;l--)
if(1.0*(h[i]-h[l])/(i-l)<mn) mn=1.0*(h[i]-h[l])/(i-l),see[l][i]=1;
for(int r=1;r<=n;r++)
for(int l=r,s=1,lst=l;l>=1;l--)
{
if(see[l][r])
{
if(!see[l+1][r]) s+=min(f[l+1][lst],f[l+1][lst+1]);
f[l][r]=s;
}
else
{
if(see[l+1][r]) lst=l;
f[l][r]=s+min(f[l][lst],f[l][lst+1]);
}
ans^=f[l][r];
}
cout<<ans<<endl;
}

后记

听说JXOI 80分就能进队什么鬼啊。。

这放在HN那不晓得有多少AK的。。

我做起来还是比较轻松吧,100+100+30。当然T2推式子的时候有一项推错了,瞟一眼题解发现这题确实是推式子才继续把它推对;T3xjb贪心过了前三个点。这些都是考场上三个半小时不一定能写出来的,所以说虽然80分可以进队,但真正如果是考试,自己又能不能不失误呢?还需要斟酌、修炼。

JXOI2018简要题解的更多相关文章

  1. Noip 2014酱油记+简要题解

    好吧,day2T1把d默认为1也是醉了,现在只能期待数据弱然后怒卡一等线吧QAQ Day0 第一次下午出发啊真是不错,才2小时左右就到了233,在车上把sao和fate补掉就到了= = 然后到宾馆之后 ...

  2. Tsinghua 2018 DSA PA2简要题解

    反正没时间写,先把简要题解(嘴巴A题)都给他写了记录一下. upd:任务倒是完成了,我也自闭了. CST2018 2-1 Meteorites: 乘法版的石子合并,堆 + 高精度. 写起来有点烦貌似. ...

  3. Codeforces 863 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 简要题解?因为最后一题太毒不想写了所以其实是部分题解... A题 传送门 题意简述:给你一个数,问你能不能通过加前导000使其成为一个回文数 ...

  4. HNOI2018简要题解

    HNOI2018简要题解 D1T1 寻宝游戏 题意 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为 ...

  5. BJOI2018简要题解

    BJOI2018简要题解 D1T1 二进制 题意 pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是 \(3\) 的倍数.他想研究对于二进制,是否也有类似的性质. 于是他生 ...

  6. CQOI2018简要题解

    CQOI2018简要题解 D1T1 破解 D-H 协议 题意 Diffie-Hellman 密钥交换协议是一种简单有效的密钥交换方法.它可以让通讯双方在没有事先约定密钥(密码)的情况下,通过不安全的信 ...

  7. AtCoder ExaWizards 2019 简要题解

    AtCoder ExaWizards 2019 简要题解 Tags:题解 link:https://atcoder.jp/contests/exawizards2019 很水的一场ARC啊,随随便便就 ...

  8. Comet OJ - Contest #2 简要题解

    Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...

  9. HNOI2019 简要题解

    HNOI 2019 简要题解 没想到自己竟也能有机会写下这篇题解呢. LOJ Luogu Day1T1 鱼 枚举\(AD\)两点后发现\(BC\)与\(EF\)相对独立,因此只需要计算合法的\(BC\ ...

随机推荐

  1. 《Inside C#》笔记(完) 程序集

    程序集内部包含了各种相关的模块.资源文件.配置文件等,将这些在功能上相关的文件整合到单个文件中,以便于部署和维护.使用C#编译器编译程序时,生成的便是程序集. 一.清单数据 a)如果编译的是独立应用程 ...

  2. Flutter 相机定制

    Flutter中与硬件相关的部分,一直都挺蛋疼的.方案基本上有两种,自己写,或者等出相关的库. 最近做的一个项目中,需要对相机做定制.有过相关模块开发经验的,就知道这种需求并不简单,况且是这种跨平台解 ...

  3. Rxjava学习(二操作符)

    操作符是为了解决对Observable对象的变换的问题,操作符用于在Observable和最终的Subscriber之间修改Observable发出的事件 1.filter filter()操作符是可 ...

  4. 基于Jmeter和Testlink的自动化测试框架研究与实施

    关于测试框架搭建的详细过程,会在另一篇文章中详细介绍:http://www.cnblogs.com/leeboke/p/6145977.html 摘 要 目前基于Jmeter的接口自动化测试框架,大多 ...

  5. centos7 Linux 安装jdk1.8

    在CentOS7上安装JDK1.8 1 通过 xshell 连接到CentOS7 服务器: 2 进入到目录 /usr/local/ 中(一般装应用环境我们都会在这个目录下装,也可自行选择目录): cd ...

  6. JavaWeb:Listener和Filter

    本文内容: Listener Filter 首发日期:2018-07-15 Listener 监听器Listener负责监听事件的发生.我们能在事件发生后执行一些自定义的操作,这就是监听器的意义. 监 ...

  7. JSON数据提取

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写.同时也方便了机器进行解析和生成.JSON在数据交换中起到了一个载体的作用 ...

  8. nginx服务器开启缓存、反向代理

    一.反向代理配置 1.反向代理服务器配置如下 反向代理就是需要这一行proxy_pass来完成.当我们要访问后端web服务器的时候,我们只需要访问代理服务器就可以了,此时代理服务器就充当后端web服务 ...

  9. Lua与C交互之基础操作(1)

    @(语言) Lua是一个嵌入式的语言,可以Lua可以作为程序库用来扩展应用的功能,也可以注册有其他语言实现的函数,这些函数可能由C语言(或其他语言)实现,可以增加一些不容易由Lua实现的功能.这就是L ...

  10. oracle+st_geometry

    最近因为性能的原因开始关注通过oracle和st_geometry直接操作数据库来解决实际业务问题.主要还是用到了“使用 SQL 处理 ST_Geometry”.对此,ESRI给出的帮助文档中的解释如 ...