POJ 3761 (组合计数)
2016-07-24 16:23
316 查看
题意:
冒泡排序一轮: 相邻之间的两个数比较, 然后交换。现在给你一个有序的数列, 从 1 - N;而且是经过 K 轮交换得来的。
问你有多少个这样的数列。
分析:
对于一个数列, 我们是有一个反序表的 Ai, 反序表中的 Ai 表示 i 左边有多少比 i 要大的数的个数。可以很容易得到反序表 和 原序列是一一对应的。 而经过冒泡排序的一轮, 是可以发现把 反序表中大于0 的数都减一的。所以刚好 K 轮冒泡就是其反序表的 Ai 的 Max 是 K。现在就是来设计 反序表了。 反序表的 Ai 值是在 [0, N-i] 的。则 i >= N-k 时, 这些值的设计方案有 (K+1)!种, 当 i < N-K 时, 有 (K+1)^ (N-K-1)种方案, 则共有方案为 K! * (K+1)^(N-K)种, ---最大值是 K 的个数--> F(K) 。 而我们是要求 至少有一个 K 的方案,则可以 F(K)- F(K-1)即可得到答案了。
Code:
//#include <bits/stdc++.h> #include <iostream> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int maxn = 1e6 + 131; typedef long long LL; typedef unsigned long long ULL; const LL mod = 20100713; LL KJ[maxn]; LL PowMod(LL a, LL n) { LL ret = 1; while(n) { if(n & 1LL) ret = ret * a % mod; a = a * a % mod; n >>= 1; } return ret; } int main() { ios::sync_with_stdio(false); KJ[0] = KJ[1] = 1; for(int i = 2; i < maxn; ++i) KJ[i] = KJ[i-1] * i % mod; int T; LL n, k; cin >> T; while(T--) { cin >> n >> k; LL ans = KJ[k]; ans = ans * (PowMod((k+1), n-k) - PowMod(k, n-k) + mod) % mod; cout << ans << endl; } return 0; }
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2159 Ancient Cipher
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- [数论]poj2635__The Embarrassed Cryptographer
- [二分图匹配]poj2446__Chessboard
- POJ1050 最大子矩阵和
- Poj 3299 Humidex