传送门。

题解:


我果然是不擅长分类讨论,心态被搞崩了。

注意到\(m<=n-2\),意味着除了1以外的位置不可能被加到a[1]两遍。

先考虑个大概:

考虑若存在\(x,x-1,…,2\)(有序)这样的,且1要么不出现,要么出现在2的左边,那么\(a[1]=\sum_{i=1}^x a[i]\)。

同样,若存在\(y,y+1,…,n\),且1要么不出现,要么出现在n的左边,那么\(a[1]=a[1]+\sum_{i=y}^n a[i]\)。

开始讨论:

1.1没有出现,直接枚举x,求出最大的y的满足\(sum>=K\),现在大概要求x要恰好,y要至少。

至少好算,恰好的话考虑用至少x减去至少x+1。

2.1出现了,1的右边只有2,,n要么不出现,要么出现在1的左边,注意这种情况下\(y->n\)的和依然会被加进a[1],同样枚举x,求出最大的y,然后我们可以列出一个限制树,若\(j\)必须在\(i\)的左边,\(link(i,j)\),根据CTS2019氪金手游那题,概率是\(\prod{1 \over siz}\),乘上总方案数便是可行的方案数。

3.把上种情况的2、n互换,求法类似。

4.1出现了,2和n都在1的右边,注意这种情况\(a[1]\)会被加两遍,同样枚举x,求最大的y,然后列出限制树,发现并不是外向树,有一条内向边,那么直接把这条边容斥即可。

Code:


#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std; const int mo = 998244353; ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
} const int N = 2e5 + 5; int T, n, m, K;
ll a[N]; ll fac[N], nf[N], ni[N]; ll C(int n, int m) {
return n < m || n < 0 || m < 0 ? 0 : fac[n] * nf[m] % mo * nf[n - m] % mo;
} ll P(int n, int m) {
return n < m || n < 0 || m < 0 ? 0 : fac[n] * nf[n - m] % mo;
} ll p[N], q[N]; ll ans; ll ca1(int x, int z) {
return (x + z <= m) ? (C(m, x) * C(m - x, z) % mo * P(n - 1 - x - z, m - x - z) % mo) : 0;
}
void calc1() {
int y = n + 1;
fd(x, m + 1, 1) {
while(y > 1 && p[x] + q[y] < K) y --;
if(p[x] + q[y] < K) continue;
int z = n - y + 1;
ans += ca1(x - 1, z);
ans -= ca1(x, z);
}
ans %= mo;
} ll ca2(int x, int z) {
if(x + z > m) return 0;
return fac[m] * C(n - (x + z), m - (x + z)) % mo * nf[x - 2] % mo * nf[z + 1] % mo * ni[x + z] % mo;
}
void calc2() {
int y = n + 1;
fd(x, m, 2) {
while(y > 1 && p[x] + q[y] < K) y --;
if(p[x] + q[y] < K) continue;
int z = n - y + 1;
if(z > 0) {
ans += ca2(x, z);
ans -= ca2(x + 1, z);
} else {
n --;
ans += ca2(x, z);
ans -= ca2(x + 1, z);
n ++;
ans += ca2(x, 1);
ans -= ca2(x + 1, 1);
}
}
} void calc3() {
int z = 1;
fo(y, n - m + 1, n) {
while(z < n && p[z] + q[y] < K) z ++;
if(p[z] + q[y] < K) continue;
int x = n - y + 2;
if(z > 1) {
ans += ca2(x, z - 1);
ans -= ca2(x + 1, z - 1);
} else {
n --;
ans += ca2(x, z - 1);
ans -= ca2(x + 1, z - 1);
n ++;
ans += ca2(x, 1);
ans -= ca2(x + 1, 1);
}
}
} ll ca4(int x, int z) {
if(x + z > m) return 0;
ll sum = nf[z] * nf[x - 2] % mo * ni[x] % mo;
sum = (sum - nf[z + 1] * nf[x - 2] % mo * ni[x + z] % mo + mo) % mo;
return C(n - (x + z), m - (x + z)) * fac[m] % mo * sum % mo;
} void calc4() {
int y = n;
fd(x, m, 2) {
while(y > 1 && p[x] + q[y] + a[1] < K) y --;
if(p[x] + q[y] + a[1] < K) continue;
int z = n - y + 1;
ans += ca4(x, z);
ans -= ca4(x + 1, z);
}
} int main() {
freopen("fake.in", "r", stdin);
freopen("fake.out", "w", stdout);
n = 2e5;
fac[0] = 1; fo(i, 1, n) fac[i] = fac[i - 1] * i % mo;
nf[n] = ksm(fac[n], mo - 2); fd(i, n, 1) nf[i - 1] = nf[i] * i % mo;
fo(i, 1, n) ni[i] = ksm(i, mo - 2);
for(scanf("%d", &T); T; T --) {
scanf("%d %d %d", &n, &m, &K);
fo(i, 1, n) scanf("%lld", &a[i]);
if(K == 0) {
pp("1\n"); continue;
}
q[n + 1] = p[0] = 0;
fo(i, 1, n) p[i] = p[i - 1] + a[i];
fd(i, n, 1) q[i] = q[i + 1] + a[i];
ans = 0;
calc1();
calc2();
calc3();
calc4();
ans = (ans % mo + mo) * ksm(P(n, m), mo - 2) % mo;
pp("%lld\n", ans);
}
}

NOIP2019模拟2019.9.20】膜拜大会(外向树容斥,分类讨论)的更多相关文章

  1. 6364. 【NOIP2019模拟2019.9.20】养马

    题目描述 题解 一种显然的水法:max(0,-(点权-边权之和*2)) 这样会挂是因为在中途体力值可能会更小,所以考虑求走完每棵子树所需的至少体力值 考虑从子树往上推求出当前点的答案 设每棵子树从根往 ...

  2. 6359. 【NOIP2019模拟2019.9.15】小ω的树(tree)(定期重构)

    题目描述 题解 qy的毒瘤题 CSP搞这种码农题当场手撕出题人 先按照边权从大到小建重构树,然后40%暴力修改+查找即可 100%可以定期重构+平衡规划,每次把B个询问拉出来建虚树,在虚树上暴力维护每 ...

  3. [JZOJ6359] 【NOIP2019模拟2019.9.15】小ω的树

    题目 题目大意 给你一棵树,带点权和边权. 要你选择一个联通子图,使得点权和乘最小边权最大. 支持修改点权操作. 思考历程 显然,最先想到的当然是重构树了-- 重构树就是在做最大生成树的时候,当两个联 ...

  4. 【2019.8.8 慈溪模拟赛 T2】query(query)(分治+分类讨论)

    分治 首先,我们考虑分治处理此问题. 每次处理区间\([l,r]\)时,我们先处理完\([l,mid]\)和\([mid+1,r]\)两个区间的答案,然后我们再考虑计算左区间与右区间之间的答案. 处理 ...

  5. [JZOJ6075]【GDOI2019模拟2019.3.20】桥【DP】【线段树】

    Description N,M<=100000,S,T<=1e9 Solution 首先可以感受一下,我们把街道看成一行,那么只有给出的2n个点的纵坐标是有用的,于是我们可以将坐标离散化至 ...

  6. 6424. 【NOIP2019模拟2019.11.13】我的订书机之恋

    题目描述 Description Input Output Sample Input 见下载 Sample Output 见下载 Data Constraint 题解 lj题卡线段树 求出每个右端点往 ...

  7. 6392. 【NOIP2019模拟2019.10.26】僵尸

    题目描述 题解 吼题但题解怎么这么迷 考虑一种和题解不同的做法(理解) 先把僵尸离散化,h相同的钦(ying)点一个大小 (可以发现这样每种情况只会被算正好一次) 计算完全被占领的方案,然后1-方案/ ...

  8. 6389. 【NOIP2019模拟2019.10.26】小w学图论

    题目描述 题解 之前做过一次 假设图建好了,设g[i]表示i->j(i<j)的个数 那么ans=∏(n-g[i]),因为连出去的必定会构成一个完全图,颜色互不相同 从n~1染色,点i的方案 ...

  9. 6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]

    题目描述 题解 随便bb 详细题解见 https://www.cnblogs.com/coldchair/p/11624979.html https://blog.csdn.net/alan_cty/ ...

随机推荐

  1. Selenium之WebDriverWait

    转自https://blog.csdn.net/duzilonglove/article/details/78455051 Selenium之WebDriverWait用法

  2. 兼容新旧浏览器的flex写法

    拷贝直接加类名即可 /* 定义 */ .flex-def { display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older W ...

  3. Andrdoid中对应用程序的行为拦截实现方式之----从Java层进行拦截

    致谢: 感谢 简行之旅的这篇blog:http://blog.csdn.net/l173864930/article/details/38455951,这篇文章是参考这篇blog的进行一步一步操作的, ...

  4. 【Spring Boot】Spring Boot项目部署到外部Tomcat容器

    一.修改项目打包方式为war包 修改pom.xml文件中packaging属性项 <packaging>war</packaging> 修改pom.xml文件增加一个依赖 &l ...

  5. HTML-参考手册: HTML 音频/视频

    ylbtech-HTML-参考手册: HTML 音频/视频 1.返回顶部 1. HTML 音频/视频 DOM 参考手册 HTML5 DOM 为 <audio> 和 <video> ...

  6. Windows操作系统架构

    用户态 用户态有四类组件,这四类组件都是以进程形式存在的,也就是说,它们都有自己的进程地址空间(其实就是一套页表). 1. System Support Processes 这些是固化的进程,也就是说 ...

  7. Device Drivers

    Types of Device Drivers Windows可能会有User-mode的驱动,但是我们只关注Kernel-Mode的驱动. WDM Drivers WDM是一种驱动模型,是比较常用的 ...

  8. shell 读取配置文件的用法

    https://blog.csdn.net/qq_36684665/article/details/81134179 亲测有用!

  9. 12.Jmeter 快速入门教程 -- 监控被测资源

    写在前面的话, 作者认为jmeter的监控被测服务器资源只是基本可用, 还好习惯了linux的各种命令和工具,所以也基本不用担心什么了.但是有了图形化的监控, 也方便给领导出报告. 怎么说也是不错的. ...

  10. 发布 Vant - 高效的 Vue 组件库,再造一个有赞移动商城也不在话下

    发布 Vant - 高效的 Vue 组件库,再造一个有赞移动商城也不在话下:https://segmentfault.com/a/1190000011377961 vantUI框架在vue项目中的应用 ...