CCPC2021 威海 810975 和 CCPC2021 网络赛(重赛) Subpermutation

810975

How many situations are there if I play n games and win m games, and the longest winning streak is k?

If we use 1 to represent victory and 0 to represent defeat, any string consisting of 0 and 1 of length n can represent a situation of an n-round game. Two situations are different if and only if the two 01 strings are different.

0n,m,k105

题解

要求最长的1连续段长度为k,并不好直接做。

考虑容斥,分析容易求的是什么。容易发现如果钦定某长为k的1连续段后剩下的随便选,那么最长1连续段长度一定是大于等于k的。

所以我们用最长1连续段长度大于等于k的方案数减去最长1连续段长度大于等于k+1的方案数即可。

现在关键在于这个最长1连续段长度大于等于k的方案数怎么求。

如果使用“钦定第一个长为k的1连续段的位置,之前的位置不能出现长度大于等于k的1连续段,之后的位置任选”的方式,并不能做。因为这个“之前的位置不能出现长度大于等于k的1连续段”的方案数不能直接算。

考虑“之前的位置也任选”,当然会算重。那么进行第二步容斥就好了。

ansk=i=1m/k(1)i1(nm+1i)(nikmik)

输出anskansk+1即可。

时间复杂度O(n)。其实这题可以直接询问k1m的答案的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int maxn = 100005;
vector < ll > fac, inv, finv;
void init() {
fac.resize(maxn);
finv.resize(maxn);
inv.resize(maxn);
fac[0] = fac[1] = 1;
inv[1] = 1;
finv[0] = finv[1] = 1;
for (int i = 2; i < maxn; i++) {
fac[i] = fac[i - 1] * i % mod;
inv[i] = mod - mod / i * inv[mod % i] % mod;
finv[i] = finv[i - 1] * inv[i] % mod;
}
}
ll binom(ll n, ll r) {
if (n < r || n < 0 || r < 0) return 0;
return fac[n] * finv[r] % mod * finv[n - r] % mod;
}
int main() {
init();
int n, m, k; cin >> n >> m >> k;
if (k == 0) {
printf("%d\n", m == 0);
return 0;
}
ll ans1 = 0, ans2 = 0;
for (ll i = 1; i * k <= m; i++) {
if (i & 1) ans1 = (ans1 + binom(n - m + 1, i) % mod * binom(n - i * k, n - m) % mod + mod) % mod;
else ans1 = (ans1 - binom(n - m + 1, i) % mod * binom(n - i * k, n - m) % mod + mod) % mod;
}
for (ll i = 1; i * (k + 1) <= m; i++) {
if (i & 1) ans2 = (ans2 + binom(n - m + 1, i) % mod * binom(n - i * (k + 1), n - m) % mod + mod) % mod;
else ans2 = (ans2 - binom(n - m + 1, i) % mod * binom(n - i * (k + 1), n - m) % mod + mod) % mod;
}
cout << (ans1 - ans2 + mod) % mod << endl;
return 0;
}

Subpermutation

A permutation of n is a sequence of length n in which each number from 1 to n appears exactly once. A full permutation of n is a sequence that connects all permutations of n into one sequence in lexicographical order. Sequence p1,p2,...,pn is lexicographically smaller than q1,q2,...,qn if pi<qi where i is the minimum index satisfying piqi

Here are some symbols used in this problem:

Symbol Definition Example
pn the full-permutation of n p3={1,2,3,1,3,2,2,1,3,2,3,1,3,1,2,3,2,1}
Sn the set of all permutations of n S3={{1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1}}
f(s,t) the number of contiguous subsequences in s that are equal to t f({1,2,12,1,2},{1,2})=2

Now given n and m, please calculate

tSmf(pn,t)mod109+7

1T105,1n106,1mn

题解

m<n

考虑某一个特定的tf(pn,t)

首先是t在大排列内部的情况,显然方案数为(nm+1)!

然后是t分成两部分t1,t2,在前后两个大排列的连接处。t1是前一个大排列的后缀,t2是后一个大排列的前缀。

如果前一个大排列的前缀也是t2,那么前一个大排列的中间部分任意排,结合t1,t2的划分数,方案数为(m1)(nm)!。有一个特殊情况,若t1是从大到小的话,那么前一个大排列的中间部分就不能也是从大到小。因为t1,t2已经包含了1m,中间的部分必然是n+1m,如果中间部分和t1都是从大到小排的话,后一个大排列的前缀就会发生变化而不再是t2

如果前一个大排列的前缀不是t2,也就是某个位置不同。考虑前一个大排列在这个位置之后的部分,它必须是从大到小排列的。由于t2中的数一定小于中间的部分的数,所以这种情况是不存在的。

统计所有的t,总答案为

ans=m!((nm+1)!+(m1)(nm)!)i=1m1(mi)(mi)!

m=n

唯一一个需要考虑的情况就是“t分成两部分t1,t2,在前后两个大排列的连接处,而前一个大排列的前缀不是t2”的情况。

那么考虑前一个大排列的前缀与t2不同的位置之后,一定是从大到小排列的。根据字典序,后一个大排列的后缀是从小到大排列的,那么一定有t2t1中的数交换位置,也就形成矛盾。

代码和m<n的情况是一样的,并不需要特判。

时间复杂度O(n+T)

constexpr int N=1e6+10;
int fac[N]={1, 1}, inv[N]={-1, 1}, ifac[N]={1, 1}, sum[N]={0, 1};
void realMain(){
int n=read<int>(), m=read<int>();
int ans=add(fac[n-m+1], mul(m-1, fac[n-m]));
ans=mul(ans, fac[m]);
ans=add(ans, MOD-mul(fac[m], sum[m-1]));
printf("%d\n", ans);
}
int main(){
int n=1e6;
for(int i=2; i<=n; ++i){
fac[i]=mul(fac[i-1], i);
inv[i]=mul(MOD-MOD/i, inv[MOD%i]);
ifac[i]=mul(ifac[i-1], inv[i]);
sum[i]=add(sum[i-1], ifac[i]);
}
for(int t=read<int>(); t--; ) realMain();
return 0;
}

posted on   autoint  阅读(90)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
历史上的今天:
2019-09-05 test20190905 ChiTongZ
2018-09-05 [ZJOI2010]基站选址

导航

点击右上角即可分享
微信分享提示