洛谷传送门
SPOJ传送门
题目描述
There are n n n players out of which at most k k k players are chosen to form the team squad. Out of those players, some subset of them are selected to form a team, and a player of the selected team is appointed as the captain of the team. Given n and k, determine how many possible configurations exist. Two configurations differ if either the players in the team squad differ, or if the number of players in the team differ, or the players in the team differ, or if the captain differs.
For example,the possible configurations for n = 2 n = 2 n=2 and k = 2 k = 2 k=2 are :
- Team squad : {1}, Team : {1}, Captain : 1
- Team squad : {2}, Team : {2}, Captain : 2
- Team squad : {1,2}, Team : {1}, Captain : 1
- Team squad : {1,2}, Team : {2}, Captain : 2
- Team squad : {1,2}, Team : {1,2}, Captain : 1
- Team squad : {1,2}, Team : {1,2}, Captain : 2
Input
The first line contains T T T the number of test cases. Each of the next T T T lines contain 2 2 2 integers ? n,k$
Output
Output T lines, one for each test case, containing the required total number of configurations. Since the answers can get very big, output the answer modulo 8388608 8388608 8388608.
Example
Sample Input :
3
2 2
7 1
5 3
Sample Output :
6
7
165
Constraints
1
≤
T
≤
10000
1 \le T \le 10000
1≤T≤10000
1
≤
k
≤
n
≤
100000
1 \le k \le n \le 100000
1≤k≤n≤100000
解题分析
原来题目是叫我们求:
∑
i
=
1
k
(
n
k
)
∑
j
=
1
i
(
k
j
)
j
\sum_{i=1}^k\binom{n}{k}\sum_{j=1}^i\binom{k}{j}j
i=1∑k(kn)j=1∑i(jk)j
然而考虑一下,实际上可以先把队长选出来, 然后后面的人随便选, 那么其实和这个是等价的:
∑
i
=
1
k
(
n
i
)
2
i
−
1
\sum_{i=1}^k\binom{n}{i}2^{i-1}
i=1∑k(in)2i−1
然后发现这个模数是什么鬼? 好像是
2
23
2^{23}
223?
那么我们就预处理出组合数前 23 23 23项, 每次算前 23 23 23项就好了(因为后面的都被模掉了)。
总复杂度 O ( 23 n + 23 T ) O(23n+23T) O(23n+23T)。
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define ll long long
#define MX 100500
const int MOD = 1 << 23;
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
ll C[MX][25];
void pre()
{
for (R int i = 0; i <= 1e5; ++i) C[i][0] = 1;
for (R int i = 1; i <= 1e5; ++i)
{
for (R int j = 1, bd = std::min(i, 24); j <= bd; ++j)
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
}
}
int main(void)
{
int T, n, k;
in(T); pre();
W (T--)
{
ll ans = 0;
in(n), in(k);
for (R int j = 1, bd = std::min(23, k); j <= bd; ++j)
(ans += C[n][j] * j % MOD * (1 << j - 1) % MOD) %= MOD;
printf("%lld\n", ans);
}
}