传送门。

题解:


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

注意到\(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. jcrop+java 后台

    //jcrop 用法 lpf //页面引入 //<link rel="stylesheet" href="${basePath}/scripts/jcrop/jqu ...

  2. OS---磁盘存储器

    1.概述 1.1 磁盘存储器  不仅  容量大.存取速度快  而且  可以随机存取: 现代计算机都配置了  磁盘存储器,以  它  为主  存放文件: 对文件 的操作,都将涉及对磁盘的访问: 1.2 ...

  3. Delphi UTF编码 UTF8Encode、UTF8Decode、URLEncode、URLDecode

    一.URL简介    URL是网页的地址,比如 http://www.cnblogs.com.Web 浏览器通过 URL 从 web 服务器请求页面.    由于URL字符串常常会包含非ASCII字符 ...

  4. boost string algorithm

    The Boost.StringAlgorithms library provides many free-standing functions for string manipulation. 1. ...

  5. MDK(keil)4.7中文注释乱码解决

    由于编码使用不统一导致别的开发环境下的文件在MDK(keil)下打开中文显示乱码,解决这一问题需要进行码制转换, 可以先将欲打开的文件转换成UTF-8格式(如在notepad中进行转换),也可以在打开 ...

  6. VC2010 CString.Format使用报错 error C2664

    error C2664: “void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t *,...)”: 不能将参数 1 ...

  7. Windows Xp Sp3官方简体中文版(原版) 纯净安装版 百度网盘下载

    百度网盘下载: 1.链接:https://pan.baidu.com/s/1o-HcKddSG6IAz_0COKhq8Q 提取码:hkhr 2.扫码下载:

  8. [NOIP模拟测试38]题解

    来自达哥的问候…… A.金 显然本题的考察点在于高精而不是裴蜀定理 根据裴蜀定理易得答案为Yes当且仅当$gcd(n,m)=1$,那么考虑怎么在高精度下判互质. 如果$n,m$都能被2整除,那么显然不 ...

  9. Arrays(二),对封装的数组进行增删改查操作

    (一)添加元素 对任意位置添加元素 /** * 向数组中添加元素 * @param e 元素e * @param index 插入元素的在数组中的位置 * @return 添加结果 */ public ...

  10. jQuery 删除行(带跨行的表格)

    jQuery 删除行(带跨行的表格) 实现效果,点击删除按钮后,在保证原来表格结构的基础上,移除当前行. 代码原理: 1.点击行后判断当前行的第一个<td>,是否包含rowspan属性,如 ...