IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> #775 Div.1 C. Tyler and Strings 组合数学 -> 正文阅读

[C++知识库]#775 Div.1 C. Tyler and Strings 组合数学

C
组合数学,1900,数状数组

题意

给出 s , t s, t s,t 两个序列,长度分别为 n , m n,m n,m,问 s s s 有多少种排序方式满足 s s s 的字典序比 t t t 小。 1 ≤ n , m ≤ 2 e 5 1\leq n,m\leq 2e5 1n,m2e5

思路

因为是按字典序比较,所以如果 s 1 < t 1 s_1<t_1 s1?<t1? 之后的就可以随便排了,所以考虑枚举前 i ? 1 i-1 i?1 位相同且 s i < t i s_i<t_i si?<ti? 的排序方式有 c n t i cnt_i cnti? 种,最后的答案就是 ∑ i = 1 i = n c n t i \sum_{i=1}^{i=n} cnt_i i=1i=n?cnti?

那么如何求 c n t i cnt_i cnti? 呢?如果不考虑可重复排列,那么 c n t i = n o w × ( n ? i ) ! cnt_i= now \times (n-i)! cnti?=now×(n?i)! ,即到第 i 位当前满足小于 t i t_i ti? 的个数乘上之后数的全排列(因为 i i i 后面的数可以随便取了)。 n o w now now 可以直接用数状数组维护前缀和(因为前 i ? 1 i-1 i?1 位两序列相同,所以可以直接将那个数字数量减1)。于是问题重点在于加上可重复排列后怎么做。

首先可重复排列要在 n ! n! n! 的基础上除以每个元素出现数量的阶乘。即当我们遍历到第 i i i 位时,要在 ( n ? i ) ! (n-i)! (n?i)! 的基础上除以 c n t 1 ! × c n t 2 ! × c n t i ! . . . . × c n t n ! {cnt_1!\times cnt_2!\times cnt_i!....\times cnt_n!} cnt1?!×cnt2?!×cnti?!....×cntn?!
其中 c n t 1 cnt_1 cnt1?减去前 i ? 1 i-1 i?1 位数字后的对应数字的数量。然后我们就可以先预处理出 i = 0 i=0 i=0 时的上式记为 fenzi,由
1 c n t 1 ! × c n t 2 ! × ( c n t i ? 1 ) ! . . . . × c n t n ! = 1 c n t 1 ! × c n t 2 ! × c n t i ! . . . . × c n t n ! × c n t i \frac{1}{cnt_1!\times cnt_2!\times (cnt_i-1)!....\times cnt_n!}=\frac{1}{cnt_1!\times cnt_2!\times cnt_i!....\times cnt_n!}\times cnt_i cnt1?!×cnt2?!×(cnti??1)!....×cntn?!1?=cnt1?!×cnt2?!×cnti?!....×cntn?!1?×cnti?,只需每次遍历后将 fenzi *= cnt[t[i]] 并更新 cnt[t[i]] 即可。

ps.不要忘记考虑 s s s 可能恰好为 t t t 的前缀的情况,开始忘了,还好有样例1

代码

void solve() {
   cin >> n >> m;
   fac[0] = 1;
   for(int i = 1; i <= n; i++) {
   	fac[i] = (fac[i-1] * i) % P;
   }
   for(int i = 1; i <= n; i++) {
   	cin >> s[i];
   	update(s[i], 1);
   	cnt[s[i]]++;
   }
   for(int i = 1; i <= m; i++) {
   	cin >> t[i];
   }
   int ans = 0;
   int mi = min(n, m);
   int fz = 1;
   for(int i = 1; i <= 2e5; i++) {
   	if(cnt[i]) {
   		fz = fz * fac[cnt[i]] % P;
   	}
   }
   fz = power(fz, P - 2);
   int flag = 1;
   if(n >= m) {
   	flag = 0;
   }
   for(int i = 1; i <= mi; i++) {
   	int p = ask(t[i] - 1);
   	ans = (ans + p * fac[n-i] % P * fz % P) % P;
   	if(!cnt[t[i]]) {
   		flag = 0;
   		break;
   	}
   	fz = fz * cnt[t[i]] % P;
   	cnt[t[i]]--;
   	update(t[i], -1);
   }
   ans += flag;
   ans %= P;
   cout << ans << endl;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 10:32:27  更:2022-07-03 10:33:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:51:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码