当前位置:网站首页>HUSTPC2022
HUSTPC2022
2022-07-02 11:55:00 【不是张胖胖】
H. Permutation Counting
思路:
有 n ( 1 ≤ n ≤ 2 ⋅ 1 0 6 ) n(1≤n≤2⋅10^6) n(1≤n≤2⋅106)个数字的全排列 a a a,已知这 n n n个数字间有 m m m个约束 x i , y i x_i,y_i xi,yi,已知 a x i < a y i a_{xi}<a_{yi} axi<ayi,且 x i x_i xi互不相同, y i y_i yi可能相同
问有多少种满足所有约束的可能?对答案模 998244353 998244353 998244353
思路:
根据约束建立有向图,若图中存在环,则认为无解。反之,则一定至少存在一种合理解。
其次,由于题目中 x i x_i xi互不相同,我们可以得知,若将 y i → x i y_i \rightarrow x_i yi→xi连边,则一定会形成森林
为了将森林变为一整颗树,加入额外点 n + 1 n+1 n+1,与所有树的树根连接,于是我们将森林变为了一整颗树
树形 d p dp dp, s z i sz_i szi表示以 i i i为树根的子树节点大小, f i f_i fi表示 s z i sz_i szi个数字在以 i i i为根的子树中,有多少种排列方法。那么
考虑将 10 10 10个不同的石头分成 5 , 3 , 2 5,3,2 5,3,2三堆
有 C 10 5 ⋅ C 5 3 ⋅ C 2 2 C_{10}^{5}⋅C_5^3⋅C_2^2 C105⋅C53⋅C22种可能
那么本题将一颗大小的 10 10 10个节点的树分为 4 , 3 , 2 4,3,2 4,3,2的子树
有 C 9 4 ⋅ C 5 3 ⋅ C 2 2 C_{9}^{4}⋅C_5^3⋅C_2^2 C94⋅C53⋅C22种可能,其中最大的数字一定是根节点。
所以只需要满足根节点最大,剩下的节点任意分即可
/* * @Author: zhangpangpang * @Date: 2022-06-09 09:29:49 * @Last Modified by: zhangpangpang * @Last Modified time: 2022-06-09 09:29:49 */
#include<bits/stdc++.h>
#define fi first
#define gcd __gcd
#define se second
#define pb push_back
#define lowbit(x) x&-x
#define inf 0x3f3f3f3f
#define mem(x,y) memset(x,y,sizeof(x))
#define lrb666 ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
typedef pair<int,int> PII;
const int maxn=2e6+7;
int n,m,fa[maxn],d[maxn];
ll mod=998244353,sz[maxn],f[maxn],fac[maxn],inv[maxn],finv[maxn];
ll ksm(ll b,ll p){
ll r=1;while(p>0){
if(p&1){
r=(r%mod*(b%mod))%mod;}p>>=1;b=(b%mod*(b%mod))%mod;}return r;}
void binom_init(int x) {
fac[0] = fac[1] = 1;
inv[1] = 1;
finv[0] = finv[1] = 1;
for(int i=2; i<x; 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 find(int x)
{
if(x==fa[x])
return fa[x];
else
return fa[x]=find(fa[x]);
}
void lianjie(int x,int y)
{
int px=find(x),py=find(y);
fa[px]=py;
}
vector<int>v[maxn];
void dfs(int u,int fa)
{
sz[u]=1;f[u]=1;
ll use=0;
for(auto nx:v[u])
{
if(u==fa) continue;
dfs(nx,u);
sz[u]+=sz[nx];
}
use++;
for(auto nx:v[u])
{
if(u==fa) continue;
f[u]=(f[u]*f[nx])%mod;
f[u]=(f[u]*binom(sz[u]-use,sz[nx]))%mod;
use+=sz[nx];
}
}
int main()
{
binom_init(maxn-5);
scanf("%d%d",&n,&m);int ok=1;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
int a,b;scanf("%d%d",&a,&b);
d[a]++;
v[b].pb(a);
if(find(a)==find(b)) ok=0;
else lianjie(a,b);
}
for(int i=1;i<=n;i++)
{
if(d[i]==0) v[n+1].pb(i);
}
if(!ok)
{
puts("0");return 0;
}
dfs(n+1,-1);
printf("%lld\n",f[n+1]);
}
边栏推荐
猜你喜欢
Obsidian installs third-party plug-ins - unable to load plug-ins
mathML转latex
Large top heap, small top heap and heap sequencing
YoloV6训练:训练自己数据集遇到的各种问题
Factal: Unsafe repository is owned by someone else Solution
报错:npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
Fundamentals of software testing
Makefile 分隔文件名与后缀
Full of knowledge points, how to use JMeter to generate encrypted data and write it to the database? Don't collect it quickly
Socket and socket address
随机推荐
Fabric.js 动态设置字号大小
Fabric. Usage of JS eraser (including recovery function)
【NOI模拟赛】伊莉斯elis(贪心,模拟)
LeetCode 209. Minimum length subarray
info [email protected] : The platform “win32“ is incompatible with this module.
Simple verification code generator for 51 single chip microcomputer experiment
ONNX+TensorRT:将预处理操作写入ONNX并完成TRT部署
数据库连接池和数据源
大顶堆、小顶堆与堆排序
Introduction to C language -- array
LeetCode_滑动窗口_中等_395.至少有 K 个重复字符的最长子串
taobao. trade. Get (get some information of a single transaction), Taobao store order interface, Taobao oauth2.0 interface, Taobao R2 interface code docking and sharing
LeetCode 2320. Count the number of ways to place the house
Find the maximum inscribed circle of the contour
使用mathtype编辑公式,复制粘贴时设置成仅包含mathjax语法的公式
LeetCode 209. 长度最小的子数组
Slashgear shares 2021 life changing technology products, which are somewhat unexpected
复用和分用
广州市应急管理局发布7月高温高湿化工安全提醒
C语言中的printf函数和scanf函数