SP5973 SELTEAM - Selecting Teams

(upd on 2021.11.1 修改了一处笔误)

题目

SP5973 SELTEAM - Selecting Teams

分析

一看就非常组合,实际上确实是个组合题。

我们先考虑直接列出柿子暴力计算:

\[\large \sum_{i=1}^k\dbinom ni\sum_{j=1}^i \dbinom ij\dbinom j1 \]

含义是先选出球队人员,再选参加比赛的人,再选出队长。

然后考虑用公式化简:

\(\large \sum\limits_{i=1}^k\dbinom ni\sum\limits_{j=1}^i \dbinom ij\dbinom j1=\sum\limits_{i=1}^k\dbinom ni\sum\limits_{j=1}^i\dbinom {i-1}{j-1}\dbinom i1=\sum\limits_{i=1}^k\dbinom nii\sum\limits_{j=0}^{i-1}\dbinom {i-1}{j}=\sum\limits_{i=1}^k\dbinom nii2^{i-1}\)

然后我们发现模数暗藏玄机,\(8388608=2^{23}\) ,因为项当中含有 \(2^{i-1}\) ,所以暴力算只需要 23 次就结束了。

代码

#include<bits/stdc++.h>
using namespace std;
//#ifdef ONLINE_JUDGE
//	#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//	char buf[1<<21],*p1=buf,*p2=buf;
//#endif
template<typename T>
inline void read(T &x){
	x=0;bool f=false;char ch=getchar();
	while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
	while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template<typename T>
inline void write(T x){
	if(x<0) x=-x,putchar('-');
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
#define ll long long
#define ull unsigned long long
#define ld long double
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pc putchar
#define PII pair<int,int>
#define rep(i,x,y) for(register int i=(x);i<=(y);i++)
#define dep(i,y,x) for(register int i=(y);i>=(x);i--)
const int MOD=8388608;
inline int inc(int x,int y){x+=y;return x>=MOD?x-MOD:x;}
inline int dec(int x,int y){x-=y;return x<0?x+MOD:x;}
inline void incc(int &x,int y){x+=y;if(x>=MOD) x-=MOD;}
inline void decc(int &x,int y){x-=y;if(x<0) x+=MOD;}
inline void chkmin(int &x,int y){if(y<x) x=y;}
inline void chkmax(int &x,int y){if(y>x) x=y;}
const int N=1e5+5,M=2e5+5,INF=1e9+7;
int n,k,C[N][25],Pow[25];
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//	ios::sync_with_stdio(false);
//	double ST=clock();
	int t;read(t);
	for(int i=0;i<=100000;i++){
		C[i][0]=1;
		for(int j=1;j<=min(i,23);j++){
			C[i][j]=inc(C[i-1][j-1],C[i-1][j]);
		}
	}
	while(t--){
		read(n),read(k);int len=min(k,23),Ans=0;
		for(int i=1;i<=len;i++) incc(Ans,1ll*C[n][i]*i%MOD*(1<<(i-1))%MOD);
		write(Ans),pc('\n');
	}
//#ifndef ONLINE_JUDGE
//	cerr<<"\nTime:"<<(clock()-ST)/CLOCKS_PER_SEC<<"s\n";
//#endif
	return 0;
}
/*
2
5 
4 1 2 4 5 3 1 2 3 5
3
3 2 1 2 1 3
*/



总结

这题告诉我们一定要注意模数等题目当中看不见的微小性质!!

posted @ 2021-10-28 20:31  __Anchor  阅读(25)  评论(0编辑  收藏  举报