题目

首先还没有安排座位的\(m-k\)个人之间是有顺序的,所以先把答案乘上\((m-k)!\),就可以把这些人看作不可区分的。

已经确定的k个人把所有座位分成了k+1段。对于第i段,如果我们能求出这一段恰好额外坐j人时的代价总和\(f_{i,j}\),并令\(f_{i,j}\)的普通生成函数为\(F_i(x)\),答案就是\(\prod F_i(x)\)的\(m-k\)次项系数。


先考虑k+1段中两边都有已经确定的人的k-1段。对于每一段i,枚举其中额外坐的人数j,现在考虑求出\(f_{i,j}\)。令\(g_i\)表示只考虑两个相邻的人,他们之间的距离为i时的代价,显然\(g_i=i\)。令\(G(x)\)为g的普通生成函数:

\[\begin{align}
G(x)&=\sum_{n>0}n\cdot x^n\\
&=x\sum_{n\geq0}(n+1)x^n\\
&=x \cdot \frac1{(1-x)^2}\\
&=\frac x {(1-x)^2}\\
\end{align}
\]

令第i段空座位两边端点之间的距离为len,发现\(f_{i,j}=G(x)^{j+1}\)的len次项系数(每j个人有j+1段空隙)。由于\(n\leq2e5\),所以可以对每一个j(\(j\geq0\))用这个公式暴力算:\(\frac{1}{(1-x)^m}=\sum_{n\geq0}\binom{n+m-1}{m-1}x^n\)。


考虑序列两头只有一边有已经确定的人的段。这里\(f_{i,j}=G(x)^j\)的0~len次项系数之和。根据上面的公式,我们实际要求的是一个组合数前缀和的形式。\(C(n,n)+C(n+1,n)+C(n+2,n)+\cdots+C(m,n)=C(m+1,n+1)\),可以根据这个直接\(O(1)\)算。


对于k=0的情况特殊处理,方法和上面处理序列两头的类似。

所以现在已经算出了每一段的\(F(x)\),项数之和是\(O(n)\)的,用分治FFT把所有\(F(x)\)卷起来即可。卷之前把所有\(F(x)\)顺序打乱,防止分治的时候被卡。时间复杂度\(O(nlog^2n)\)。

点击查看代码
#include <bits/stdc++.h>
#include <atcoder/all> #define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <int,int>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back using namespace std;
using mint=atcoder::modint998244353; const LL MOD=998244353; LL qpow(LL x,LL a)
{
LL res=x,ret=1;
while(a>0)
{
if((a&1)==1) ret=ret*res%MOD;
a>>=1;
res=res*res%MOD;
}
return ret;
} LL n,m,k,a[200010],fac[400010],inv[400010];
vector <vector <mint> > v; LL C(LL nn,LL mm){return fac[nn]*inv[mm]%MOD*inv[nn-mm]%MOD;} void deal(LL emp)
{
if(emp<=0) return;
vector <mint> tmp;tmp.pb(1);
repn(seg,emp) tmp.pb(C(emp+seg,seg+seg));
v.pb(tmp);
} vector <mint> solve(LL lb,LL ub)
{
if(lb==ub) return v[lb];
return atcoder::convolution(solve(lb,(lb+ub)/2),solve((lb+ub)/2+1,ub));
} int main()
{
fac[0]=1;repn(i,400005) fac[i]=fac[i-1]*(LL)i%MOD;
rep(i,400003) inv[i]=qpow(fac[i],MOD-2);
cin>>n>>m>>k;
rep(i,k) scanf("%lld",&a[i]);
if(k==0)
{
LL seg=m-1,res=0;
for(LL len=m-1;len<n;++len) (res+=C(len+seg-1,seg+seg-1)*(n-len))%=MOD;
cout<<res*fac[m]%MOD<<endl;
return 0;
}
rep(i,k-1)
{
LL len=a[i+1]-a[i];
vector <mint> tmp;
repn(seg,len)
{
LL val=C(len+seg-1,seg+seg-1);
tmp.pb(val);
}
v.pb(tmp);
}
deal(a[0]-1);deal(n-a[k-1]);
random_shuffle(v.begin(),v.end());
vector <mint> ans=solve(0,v.size()-1);
cout<<(LL)ans[m-k].val()*fac[m-k]%MOD<<endl;
return 0;
}

[题解] Atcoder ABC 225 H Social Distance 2 生成函数,分治FFT的更多相关文章

  1. [题解] Atcoder ABC 213 H Stroll DP,分治FFT

    题目 令\(dp_{i,j}\)表示从点1到达点i,路径长度为j的方案数.转移为\(dp_{i,j}=\sum_{(i,v,w)\in E}dp_{v,j-w}p_{i,v,w}\). 显然只能从长度 ...

  2. AtCoder ABC 242 题解

    AtCoder ABC 242 题解 A T-shirt 排名前 \(A\) 可得 T-shirt 排名 \([A+1,B]\) 中随机选 \(C\) 个得 T-shirt 给出排名 \(X\) ,求 ...

  3. atcoder abc 244

    atcoder abc 244 D - swap hats 给定两个 R,G,B 的排列 进行刚好 \(10^{18}\) 次操作,每一次选择两个交换 问最后能否相同 刚好 \(10^{18}\) 次 ...

  4. AtCoder ABC 250 总结

    AtCoder ABC 250 总结 总体 连续若干次一样的结果:30min 切前 4 题,剩下卡在 T5 这几次卡在 T5 都是一次比一次接近, 什么 dp 前缀和打挂,精度被卡,能水过的题连水法都 ...

  5. ATCODER ABC 099

    ATCODER ABC 099 记录一下自己第一场AK的比赛吧...虽然还是被各种踩... 只能说ABC确实是比较容易. A 题目大意 给你一个数(1~1999),让你判断它是不是大于999. Sol ...

  6. Atcoder ABC 141

    Atcoder ABC 141 A - Weather Prediction SB题啊,不讲. #include<iostream> #include<cstdio> #inc ...

  7. Atcoder ABC 139E

    Atcoder ABC 139E 题意: n支球队大循环赛,每支队伍一天只能打一场,求最少几天能打完. 解法: 考虑抽象图论模型,既然一天只能打一场,那么就把每一支球队和它需要交手的球队连边. 求出拓 ...

  8. Atcoder ABC 139D

    Atcoder ABC 139D 解法: 等差数列求和公式,记得开 $ long long $ CODE: #include<iostream> #include<cstdio> ...

  9. Atcoder ABC 139C

    Atcoder ABC 139C 题意: 有 $ n $ 个正方形,选择一个起始位置,使得从这个位置向右的小于等于这个正方形的高度的数量最多. 解法: 简单递推. CODE: #include< ...

随机推荐

  1. GDOI 2022 普及组游记

    To LuoguDAY -1 期中考成绩下来了,全无了除了历史 (96) 和生物 (95) 还能看,剩下的-,语文 101.5 ,少错一道选择和断句就 107.5 了,居然比雌兔还低 数学少错一道选择 ...

  2. vue使用vuex报错 "export 'watch' was not found in 'vue'

    问题 安装Vuex后报错"export 'watch' was not found in 'vue' 解决方法 如果你的vue版本是 2.X ,将vuex升到 3.X.X 就能够解决 npm ...

  3. maven项目(引入依赖失败, pom.xml 报错\爆红)

    引入项目过程中,idea引入磁盘的某个的maven项目 这里以springboot项目以例子,发现pom.xml 的依赖大面积爆红,springboot的版本依赖也报错了,然后发现下面有进度条在下载, ...

  4. 丽泽普及2022交流赛day19 半社论

    目录 No Problem Str Not TSP 题面 题解 代码 Game 题面 题解 代码 No Problem 暴力 Str 存在循环节,大力找出来即可,长度显然不超过 \(10^3\) . ...

  5. Windows Embedded CE 6.0开发环境的搭建(2)

    最近开始在学习嵌入式,在这里首先得安装Windows Embedded CE 6.0,其中遇到了很多问题,电脑的系统以及相关配置都会在安装过程中受到影响,因此笔者就安装中的问题以及环境搭建来介绍一下. ...

  6. ROS机械臂 Movelt 学习笔记4 | Move Group 接口 Python

    Python 的使用总是比 C++ 简单许多,Move Group 的 Python 接口更为便捷,也为使用者提供了很多用于操纵机器人和机械臂的函数,能够和 C++ 接口实现相同的功能: 设置机械臂的 ...

  7. Luogu1655 小朋友的球 (组合数学,第二类斯特林数,高精)

    我bingoyes再高精用STL就饿死,死外边! string真的爽... 斯特林数模板题:\(S(n,m) = S(n-1,m-1)+S(n-1,m)*n\) #include <iostre ...

  8. kubernetes网络模型

    Overview 本文将探讨Kubernetes中的网络模型,以及对各种网络模型进行分析. Underlay Network Model 什么是Underlay Network 底层网络 Underl ...

  9. 若依 | 点击顶部 tag 标签不自动刷新

    需求场景 之前:只要点击若依顶部的标签,页面都会自动刷新. 问题:A 页面有查询结果,切换到 B 页面查看信息,再切回 A 页面,则 A 页面的查询结果不会保留. 需求:点击标签,页面不自动刷新,或者 ...

  10. 给ShardingSphere提了个PR,不知道是不是嫌弃我

    说来惭愧,干了 10 来年程序员,还没有给开源做过任何贡献,以前只知道嘎嘎写,出了问题嘎嘎改,从来没想过提个 PR 去修复他,最近碰到个问题,发现挺简单的,就随手提了个 PR 过去. 问题 问题挺简单 ...