题面
题解
第一问很简单, 如果 \(n - k\) 是偶数那么答案就是 \(2 ^ k - 1\) , 如果 \(n - k\) 是奇数答案就是 \(2^k - 2\)
第二问怎么办, 我们对于 \(n - k\) 是偶数讨论
我们要做的是, 对于每一个数, 我们要让他选奇数次最后的答案可能性才会最大
并且所有的数选的次数加起来是 \(n\)
我们考虑指数型生成函数 \(\frac{e^x-e^{-x}}{2}\)
把它展开后, 偶数位都是 \(0\) , 奇数位都是 \(1\)
那么我们只要求 \(\frac{e^x-e^{-x}}{2}^k\) 在 \(x ^ n\) 上的系数即可
如果 \(n - k\) 是奇数的话就变成求 \(\frac{e^x-e^{-x}}{2}^{k-1}*\frac{e^x+e^{-x}}{2}\) 在 \(x^n\) 上的系数, 即 \(1\) 取偶数个, 其他的都取奇数个
二项式定理展开即可
注意最后答案还要乘上一个 \(n!\) 因为我们算出来的是无序方案, 但答案事实上是求有序方案
Code
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> const int N = 100005; const int mod = 1e9 + 7; using namespace std; int T, n, k, fac[N], inv[N], pow[N], ans; template < typename T > inline T read() { T x = 0, w = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * w; } int fpow(int x, int y) { int res = 1; for( ; y; y >>= 1, x = 1ll * x * x % mod) if(y & 1) res = 1ll * res * x % mod; return res; } int C(int n, int m) { return 1ll * fac[n] * inv[n - m] % mod * inv[m] % mod; } int main() { T = read <int> (); for(int i = (pow[0] = fac[0] = 1); i <= 100000; i++) { fac[i] = 1ll * fac[i - 1] * i % mod; if(i == 1) pow[i] = 1ll * pow[0] * fpow(2, mod - 2) % mod; else pow[i] = 1ll * pow[i - 1] * pow[1] % mod; } inv[100000] = fpow(fac[100000], mod - 2); for(int i = 99999; i >= 0; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod; while(T--) { n = read <int> (), k = read <int> (); ans = 0; if(!((n - k) & 1)) { printf("%d ", (fpow(2, k) - 1 + mod) % mod); for(int op = (k & 1 ? mod - 1 : 1), i = 0; i <= k; i++, op = mod - op) ans = (ans + 1ll * op * C(k, i) % mod * fpow(2 * i - k + mod, n) % mod) % mod; ans = 1ll * ans * pow[k] % mod; printf("%d\n", ans); } else { printf("%d ", (fpow(2, k) - 2 + mod) % mod); for(int op = (k & 1 ? 1 : mod - 1), i = 0; i < k; i++, op = mod - op) ans = (ans + 1ll * op * C(k - 1, i) % mod * (fpow(2 * i - k + 2 + mod, n) + fpow(2 * i - k + mod, n)) % mod) % mod; ans = 1ll * ans * pow[k] % mod; printf("%d\n", ans); } } return 0; }
来源:https://www.cnblogs.com/ztlztl/p/12208179.html