[SP5973] SELTEAM - Selecting Teams

洛谷传送门
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 :

  1. Team squad : {1}, Team : {1}, Captain : 1
  2. Team squad : {2}, Team : {2}, Captain : 2
  3. Team squad : {1,2}, Team : {1}, Captain : 1
  4. Team squad : {1,2}, Team : {2}, Captain : 2
  5. Team squad : {1,2}, Team : {1,2}, Captain : 1
  6. 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 1T10000
1 ≤ k ≤ n ≤ 100000 1 \le k \le n \le 100000 1kn100000

解题分析

原来题目是叫我们求:
∑ 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=1k(kn)j=1i(jk)j
然而考虑一下,实际上可以先把队长选出来, 然后后面的人随便选, 那么其实和这个是等价的:
∑ i = 1 k ( n i ) 2 i − 1 \sum_{i=1}^k\binom{n}{i}2^{i-1} i=1k(in)2i1
然后发现这个模数是什么鬼? 好像是 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);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值