赞
踩
前言:我们平时遇到的组合数如果用杨辉三角型做的话,预处理的复杂度是 n 2 n^2 n2 ,遇到大一点的数据就会爆炸
我们怎么去优化呢
C
(
n
,
k
)
=
n
!
k
!
⋅
(
n
−
k
)
!
m
o
d
mod
C(n, k) = \frac{n!}{k! \cdot (n-k)!} \mod \text{mod}
C(n,k)=k!⋅(n−k)!n!modmod
答案太大我们会进行取模,那么我们就可以利用费马小定理
所以我们可以对我们的分母乘积进行逆元操作
但是我们的阶乘进行预处理
我们再来看一下下面这个题目,分析我们得知,只有我们选取的 1 的个数是大于等于 k /2 +1 的,才是有价值的
所以我们可以用组合数的方法进行
有一个易错点,我们预处理的时候,阶乘的 a[ 0 ] = 1 , 否则会出错
#include<bits/stdc++.h> using namespace std; #define int long long // 1 2 3 const int Mod = (int)1e9 + 7; int n, k; const int N = (int)2e5 + 5; int a[N]; void ini() { a[1] = 1; a[0] = 1; for (int i = 2; i < N; i++) { a[i] = (a[i - 1] * i) % Mod; } } int qw(int x, int p) { int t = 1; while (p) { if (p & 1) t = (t * x) % Mod; x = (x * x) % Mod; p >>= 1; } return t; } int C(int n, int k) { if (n < k) return 0LL; return (a[n] % Mod) * (qw(a[n - k] * a[k] % Mod, Mod - 2) % Mod) % Mod; } signed main() { int t; ini(); //for (int i = 1; i <= 10; i++) cout << a[i] << endl; //cout << qw(2, 2); cin >> t; while (t--) { cin >> n >> k; int one = 0; for (int i = 1; i <= n; i++) { int u; cin >> u; if (u) one++; } int ans = 0; for (int i = k / 2 + 1; i <= min(one, k); i++) { int t = C(one, i) * C(n - one, (k - i)) % Mod; ans = (ans + t) % Mod; } cout << ans << endl; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。