文章目录

  • H. Permutation Counting

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];elsereturn 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]);
}

HUSTPC2022相关推荐

最新文章

  1. 学习压缩感知比较好的文章链接收藏
  2. python值nonzero函数的解析
  3. 树莓派3b python3.6.1 SSL模块调用不起来的坑
  4. java接监控摄像头接口_离奇!深夜隧道内,12个摄像头突然一个接一个“瞎”了,监控员吓懵了...
  5. 用python内置函数算复杂度吗_番外篇: Python 面试感受
  6. HttpClient中的各种请求
  7. 滑动窗口限流 java_Spring Boot 的接口限流算法优缺点深度分析
  8. mysql 删除记录代码_mysql 删除记录时报错
  9. 计算机科学与技术大学生职业规划,计算机科学与技术大学生职业生涯规划ppt
  10. java分隔符 字符串_我们如何使用Java分割带有任何空白字符作为分隔符的字符串?...
  11. 使用 jsbarcode 生成条形码
  12. 中国银行计算机笔试题库,中国银行笔试真题-计算机部分
  13. 低延迟视频传输 UDP JPEG图像压缩 opencv
  14. JS调用google DEMO朗读
  15. 三角波c语言编程,51单片机简易波形发生器(正弦波 锯齿波 三角波)仿真+源程序+电路原理图...
  16. 微云html网页,微云收藏在哪里_以及腾讯微云收藏网页版怎么用? - 软件教程 - 格子啦...
  17. python的工具库谁写_python工具库库介绍-bidict: 双向字典
  18. 阿里云一级域名跳转https的二级域名配置说明(主域名跳转子域名, 不带www跳带www)
  19. 【案例】某市规范性文件合法性审核信息管理系统和行政执法监督平台建设案例
  20. Divide by Zero 2021 and Codeforces Round #714 (Div. 2)B. AND Sequences(位运算 + 思维 + 排列)

热门文章

  1. 用Excel为人生铺路,走向希望的彼岸
  2. 【学习记录】合并排序(归并排序)-分治法-计算机算法
  3. Google Map Event 谷歌地图事件
  4. 下载及配置maven详细步骤
  5. android8.1谷歌相机,谷歌相机8.1成功被移植,适用于大多数非Pixel安卓手机
  6. Python打卡四——字符串讲解
  7. 家用简单电线路图_家庭电路安装走线图解析,教你4步快速布线
  8. Linux学习:Linux基础命令集(1)
  9. C#产生随机数之一 生成真随机数
  10. 基于Spark的大数据精准营销中搜狗搜索引擎的用户画像挖掘