D
题意:
给你n个花,让你选大于等于1朵花组成花束,花束的个数不能为a或b。
解法:
2^n - 1 - C(n)(a) - C(n)(b)
#include <bits/stdc++.h>
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, a, b) for (int i = (int)(a); i >= (int)b; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define ms(x, y) memset(x, y, sizeof(x))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef pair<i64, i64> pi64;
typedef double ld;
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }
const i64 mod = (i64)1e9 + 7;
i64 n, a, b;
i64 quickmod(i64 a, i64 b, i64 c) {
i64 ans = 1;
while(b) {
if(b & 1) {
ans = (ans * a) % c;
}
a = (a * a) % c;
b >>= 1;
}
return ans;
}
i64 cc(i64 x, i64 y) {
i64 tmp = 1;
for (i64 i = x; i >= x - y + 1; --i) tmp = tmp * i % mod;
for (i64 i = 1; i <= y; ++i) tmp = tmp * quickmod(i, mod - 2, mod) % mod;
return tmp;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFIN
freopen("input.txt", "r", stdin);
#endif
cin >> n >> a >> b;
i64 ans = quickmod(2, n, mod) - 1 - cc(n, a) - cc(n, b);
ans = (ans % mod + mod) % mod;
cout << ans << '\n';
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}
E
题意:
一开始有n个房间,每个房间各有一个人,现定义一次操作可以让一个房间的人走到另一个房间去,给你k个操作,问你能产生多少种不同的情况。
思路:
对于每一个房间都有空和非空两种状态,因为最多有(n-1)个房间是空的,所以空的房间可能的个数为0~min(n - 1, k),所以遍历所有可能的空房间的数量i,如果有i个空房间,非空房间的所有情况个数为C(n - 1)(n - i - 1), 空房间的可能情况为C(n)(i),所以每次答案加上
C(n)(i) * C(n - 1)(n - i - 1)再取模。
#include <bits/stdc++.h>
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, a, b) for (int i = (int)(a); i >= (int)b; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define ms(x, y) memset(x, y, sizeof(x))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef pair<i64, i64> pi64;
typedef double ld;
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }
const i64 mod = (i64)1e9 + 7;
i64 n, k;
const i64 maxn = 2 * (i64)1e5 + 1000;
i64 fac[maxn],inv[maxn];
i64 pow_mod(i64 a,i64 n)
{
i64 ret =1;
while(n)
{
if(n&1) ret=ret*a%mod;
a=a*a%mod;
n>>=1;
}
return ret;
}
void init()
{
fac[0]=1;
for(i64 i=1;i<maxn;i++)
{
fac[i]=fac[i-1]*i%mod;
}
}
i64 CC(i64 x, i64 y)
{
return fac[x]*pow_mod(fac[y]*fac[x-y]%mod,mod-2)%mod;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFIN
freopen("input.txt", "r", stdin);
#endif
init();
cin >> n >> k;
i64 noPeople = min(n - 1, k);
i64 ans = 0;
for (i64 i = 0; i <= noPeople; ++i) {
ans = (ans + (CC(n, i) * CC(n - 1, n - i - 1)) % mod) % mod;
}
cout << ans << '\n';
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}