Loj #6244. 七选五

Posted 蒟蒻JHY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Loj #6244. 七选五相关的知识,希望对你有一定的参考价值。

link: https://loj.ac/problem/6244

 

让我们设B=N-K,再设F(P)为从1~P+B中选P个数(有序的),且这P个数是一个错排(即不存在一个i使得 i=Ai ,其中A是选出的有序的P个数)的方案数。

再设G(P)为从1~P+B中选出P个数的方案数。

 

有几个显然的结论:

1.G(P)=P(P+B,P)

2.ANS=C(K,X)*F(K-X) ,考虑x个相同的是哪些元素。。。

3.G(P)=Σ F(i) * C(P,i)  ,考虑有几个元素和原来相同。。。

 

因为3.可以用来二项式反演,然后再结合1.就可以求出F(K-X),然后直接得到答案。

#include<bits/stdc++.h>
#define ll long long
#define maxn 1000000
using namespace std;
const int ha=1000000007;
int jc[maxn+5],ni[maxn+5];
int N,X,K,B;

inline int add(int x,int y){
	x+=y;
	return x>=ha?x-ha:x;
}

inline int ksm(int x,int y){
	int an=1;
	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
	return an;
}

inline void init(){
	jc[0]=1;
	for(int i=1;i<=maxn;i++) jc[i]=jc[i-1]*(ll)i%ha;
	ni[maxn]=ksm(jc[maxn],ha-2);
	for(int i=maxn;i;i--) ni[i-1]=ni[i]*(ll)i%ha;
}

inline int P(int x,int y){
	return x<y?0:jc[x]*(ll)ni[x-y]%ha;
}

inline int C(int x,int y){
	return x<y?0:P(x,y)*(ll)ni[y]%ha;
}

inline int F(int x){
	int an=0;
	for(int i=0;i<=x;i++)
	    if((x-i)&1) an=add(an,ha-P(i+B,i)*(ll)C(x,i)%ha);
	    else an=add(an,P(i+B,i)*(ll)C(x,i)%ha);
	
	return an;
}

inline int calc(){
	return C(K,X)*(ll)F(K-X)%ha;
}

int main(){
	init();
	scanf("%d%d%d",&N,&K,&X);
	B=N-K;
	printf("%d\n",calc());
}

  

以上是关于Loj #6244. 七选五的主要内容,如果未能解决你的问题,请参考以下文章

“超级福利七选一”赠书活动名单公告

linux官方下载选那个

Loj 6285. 数列分块入门 9

loj#2076. 「JSOI2016」炸弹攻击 模拟退火

loj#6281. 数列分块入门 5

loj#2071. 「JSOI2016」最佳团体