题目链接

戳我

\(Solution\)

\(50\ pts\)

我们来看一下题目,可以很容易的写出来答案的式子:

\[\frac{(n+m)!}{a_1!a_2!...a_{tot}!}
\]

\(a_1,a_2,...,a_{tot}\)为\(n+m\)个数中不同的数出现的个数

那么\(50\)便很好想了.

我们现在要求的是期望轮数最多,所以\({a_1!a_2!...a_{tot}!}\)要尽量小

所以我们可以贪心求解,每次找出\([l,r]\)中出现次数最少的数,找\(m\)次即可,这用个堆维护一下就好了

\(100 \ pts\)

我们还是需要\({a_1!a_2!...a_{tot}!}\)尽量小

于是我们可以二分出\(a_1,a_2,...,a_{tot}\)中的最小值的最大值,我们令这个值为\(ans\)

那么我们现在就可以知道了\(a_1,a_2,...,a_{tot}\)的分布

对于\(>ans\)的或不在[l,r]这个区间内的,直接将他们阶乘乘起来即可.

对于[l,r]内个数\(<=ans\)的,进行如下操作:

算出将[l,r]内个数\(<=ans\)的边成\(ans\)后剩下\(m\)个数还剩下几个.我们令这个数为\(c\),[l,r]内去见个数\(<=ans\)的数有\(k\)个

我们将这\(c\)个数分成不同的\(c\)个插入数列即可.

所以现在的个数为:

\(c\) 个个数为 \(ans+1\)

\(k-c\)个个数为 \(ans\)

直接快速幂求,最后吧求的乘起来,用\((n+m)!\)除他就好了.

\(Code\)

#include<bits/stdc++.h>
#define int long long
#define rg register
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
const int mod=998244353;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return f*x;
}
int n,m,tot,a[2000010],sum[2000010];
inline int check(int x,int len){
int ans=0,flag=0;
for(int i=1;i<=tot;i++){
if(sum[i]>x)
break;
ans+=sum[i],flag=i;
}
int k=(len-tot+flag);
return m-(k*x-ans);
}
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)
ans=ans*a%mod;
a=a*a%mod,b>>=1;
}
return ans;
}
int jc[20000010];
main(){
int T=read(),l,r;
jc[0]=1;
for(int i=1;i<=10200000;i++)
jc[i]=jc[i-1]*i%mod;
while(T--){
n=read(),m=read(),l=read(),r=read(),tot=0;
for(int i=1;i<=n;i++)
a[i]=read();
sort(a+1,a+1+n);
int p=0,js=1;
a[n+1]=-2147483647;
for(int i=1;i<=n+1;i++){
if(a[i]!=a[i+1]){
if(a[i]<=r&&a[i]>=l)
sum[++tot]=i-p;
else js=js*jc[(i-p)]%mod;
p=i;
}
}
sort(sum+1,sum+1+tot);
int L=0,R=m+n,maxx=0;
while(L<=R){
int mid=(L+R)>>1;
if(check(mid,(r-l+1))>=0)
L=mid+1,maxx=max(maxx,mid);
else R=mid-1;
}
int ans=0,flag=0,len=(r-l+1);
for(int i=1;i<=tot;i++) {
if(sum[i]>maxx) break;
ans+=sum[i],flag=i;
}
int k=(len-tot+flag),c=m-(k*maxx-ans);
for(int i=flag+1;i<=tot;i++) js=js*jc[sum[i]]%mod;
js=js*ksm(jc[maxx+1],c)%mod,js=js*ksm(jc[maxx],k-c)%mod;
printf("%lld\n",jc[n+m]*ksm(js,mod-2)%mod);
}
return 0;
}

最新文章

  1. gcc命令中参数c和o混合使用的详解[转载]
  2. sql服务器启动不了问题
  3. 最小生成二叉树-prim算法
  4. java基础比较好的笔记总结
  5. FIFO页面置换算法
  6. Apache模块 mod_proxy 转自http://www.php100.com/manual/apache2/mod/mod_proxy.html
  7. [Flex] ButtonBar系列——flex3 ButtonBar样式之颜色的填充
  8. Asp.Net BulletedList
  9. django 时间计数
  10. KVM下windows虚拟机使用virtio驱动
  11. Java内存分配之堆、栈和常量池
  12. 基于Vue的页面切换左右滑动效果
  13. prototype 原型链
  14. PHP中关于PDO数据访问抽象层的功能操作
  15. c++与java的几个不同点
  16. Java Observer接口和Observable类实现观察者模式
  17. 使用cookie记录页面跳转次数,然后从最后一级页面跳转回首页面
  18. phpcms 操作数据库 增删改查
  19. x的奇幻之旅 (史蒂夫&#183;斯托加茨 著)
  20. asp 月末 月初

热门文章

  1. Python面向对象相关知识1
  2. PHP 数组中出现中文乱码,json_encode返回结果为null 或false
  3. Android和Unity混合开发——解决方案
  4. Node.js中流程控制
  5. sqlserver全备份,差异备份和日志备份
  6. PythonQt第一例
  7. Linux cheat命令
  8. p1501 [国家集训队]Tree II
  9. python2.7 跨文件全局变量的方法-乾颐堂
  10. PHP中PSR