luoguP4859는 더 이상 두려울 게 없어요.

1861 단어

luoguP4859는 더 이상 두려울 게 없어요.


천국을 제사 지내는 bzoj.
luogu

해제 시간


먼저 $n - k $를 홀수로 특판하였습니다.
$m = (n + k)/2$는 $A>B $의 개수입니다.
흠정을 바로 고치다.
$dp(i, j)$를 설정하여 $A$의 이전 $i$개수를 고려하여 $j$가 $A>B$에 대한 방안 수를 정합니다.
$g(i) = dp(n, i)\times(n - i)!$가 지정되었습니다.
그리고 직접 2항식 반전 $f (m) =\sum\limits{ i = m }^{ n } ( - 1 )^{ i - m }\binom{ i }{ m } g( i ) $ .

코드

#include
using namespace std;
typedef long long lint;
struct pat{int x,y;pat(int x=0,int y=0):x(x),y(y){}bool operatorinline void read(TP &tar)
{
	TP ret=0,f=1;char ch=getchar();
	while(ch'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){ret=ret*10+(ch-'0');ch=getchar();}
	tar=ret*f;
}
namespace RKK
{
const int N=2011,mo=1000000009;
lint add(lint a,lint b){return (a+=b)>=mo?a-mo:a;}
void doadd(lint &a,lint b){if(b<0) b+=mo;if((a+=b)>=mo) a-=mo;}
lint fac[N],c[N][N];
void init()
{
	fac[0]=1;for(int i=1;i<=2000;i++) fac[i]=fac[i-1]*i%mo;
	for(int i=0;i<=2000;i++) c[i][0]=1;
	for(int i=1;i<=2000;i++)for(int j=1;j<=i;j++) c[i][j]=add(c[i-1][j-1],c[i-1][j]);
}
int n,m,a[N],b[N];
lint dp[N][N],ans;
int main()
{
	init(),read(n),read(m);for(int i=1;i<=n;i++) read(a[i]);for(int i=1;i<=n;i++) read(b[i]);sort(a+1,a+1+n),sort(b+1,b+1+n);
	if((n-m)&1){puts("0");return 0;}m=(n+m)/2;
	for(int i=0;i<=n;i++) dp[i][0]=1;
	for(int i=1,k=1;i<=n;i++)
	{
		while(k<=n&&a[i]>b[k]) k++;
		for(int j=1;j<=n;j++) dp[i][j]=add(dp[i-1][j],dp[i-1][j-1]*(k-j)%mo);
	}
	for(int i=m;i<=n;i++) doadd(ans,(((i-m)&1)?-1ll:1ll)*c[i][m]*dp[n][i]%mo*fac[n-i]%mo);
	printf("%lld
",ans); return 0; } } int main(){return RKK::main();}

좋은 웹페이지 즐겨찾기