zoukankan      html  css  js  c++  java
  • [TJOI2019] 唱、跳、rap和篮球

    怎么做的??

    考虑至少有k组人在讨论cxk,给他们按位置的因数是C(n-3k,k)

    剩下n-4k个位置,设第i类人物出现了di个,

    满足d0+d1+d2+d3=n-4k,di+k<=pi,pi是第i类任务的总数

    容易发现给这些人排位置的因数是(n-4k)!/(d0!d1!d2!d3!)

    上边这玩意儿不就是卷积么。

    把这两个因数相乘就得到k的答案了。

    取k=1到n各做一遍,最后容斥得到?答案。

    时间复杂度O(n2logn)。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=1000+5;
    const int mod=998244353;
    
    int C[N][N],n,num[N];
    int fac[N<<2],inv[N<<2],rev[N<<2],b[5][N<<2];
    
    inline int qpow(int x,int y) {
    	int c=1;
    	for(; y; y>>=1,x=1LL*x*x%mod) 
    		if(y&1) c=1LL*c*x%mod;
    	return c;
    }
    inline void ntt(int*a,int lmt,int flag) {
    	for(int i=0; i<lmt; ++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
    	for(int m=1; m<lmt; m<<=1) {
    		int wm=qpow(3,(mod-1)/(m<<1));
    		if(flag==-1) wm=qpow(wm,mod-2);
    		for(int i=0; i<lmt; i+=(m<<1)) {
    			int w=1,tmp;
    			for(int j=0; j<m; ++j,w=1LL*w*wm%mod) {
    				tmp=1LL*a[i+j+m]*w%mod;
    				a[i+j+m]=(a[i+j]-tmp+mod)%mod;
    				a[i+j]=(a[i+j]+tmp)%mod;
    			}
    		}
    	}
    	if(flag!=-1) return;
    	int tmp=qpow(lmt,mod-2);
    	for(int i=0; i<lmt; ++i) a[i]=1LL*a[i]*tmp%mod;
    }
    inline int calc(int k) {
    	int lmt=1,l=0;
    	while(lmt<=max((num[4]-k)<<2,(n-4*k)<<1)) lmt<<=1,l++;
    	for(int i=0; i<lmt; ++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    	for(int i=1; i<=4; ++i) {
    		int ret=num[i]-k;
    		for(int j=0; j<=ret; ++j) b[i][j]=inv[j];
    		for(int j=ret+1; j<lmt; ++j) b[i][j]=0;
    		ntt(b[i],lmt,1);
    	}
    	for(int i=2; i<=4; ++i) for(int j=0; j<lmt; ++j) 
    		b[1][j]=1LL*b[1][j]*b[i][j]%mod;
    	ntt(b[1],lmt,-1);
    	return 1LL*b[1][n-4*k]*fac[n-4*k]%mod;
    }
    
    int main() {
    	scanf("%d",&n);
    	for(int i=1; i<=4; ++i) scanf("%d",&num[i]);
    	for(int i=0; i<=n; ++i) {
    		C[i][0]=1;
    		for(int j=1; j<=i; ++j) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    	}
    	sort(num+1,num+5);
    	fac[0]=fac[1]=inv[0]=inv[1]=1;
    	for(int i=2; i<N; ++i) {
    		fac[i]=1LL*fac[i-1]*i%mod;
    		inv[i]=qpow(fac[i],mod-2);
    	}
    	int ans=0,c=1;
    	for(int i=0; (i<<2)<=min(n,num[1]<<2); ++i) {
    		ans=((ans+1LL*c*C[n-3*i][i]%mod*calc(i)%mod)%mod+mod)%mod;
    		c*=-1;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    又去蒯人题解,怎么这副德行

    律师函警告

  • 相关阅读:
    hdu 5646 DZY Loves Partition
    bzoj 1001 狼抓兔子 平面图最小割
    poj 1815 Friendship 最小割 拆点 输出字典序
    spoj 1693 Coconuts 最小割 二者取其一式
    hdu 5643 King's Game 约瑟夫环变形
    约瑟夫环问题
    hdu 5642 King's Order
    CodeForces 631C Report
    1039: C语言程序设计教程(第三版)课后习题9.4
    1043: C语言程序设计教程(第三版)课后习题10.1
  • 原文地址:https://www.cnblogs.com/nosta/p/10816612.html
Copyright © 2011-2022 走看看