zoukankan      html  css  js  c++  java
  • #分治NTT,容斥定理,排列组合#LOJ 6503 「雅礼集训 2018 Day4」Magic

    题目

    桌面上摆放着 (m) 种魔术卡,共 (n) 张,第 (i) 种魔术卡数量为 (a_i),魔术卡顺次摆放,形成一个长度为 (n) 的魔术序列,

    在魔术序列中,若两张相邻魔术卡的种类相同,则它们被称为一个魔术对。

    两个魔术序列本质不同,当且仅当存在至少一个位置,使得两个魔术序列这个位置上的魔术卡的种类不同,

    求本质不同的恰好包含 (k) 个魔术对的魔术序列的数量,答案对 (998244353) 取模。


    分析

    考虑给种类相同的也存在次序,最后再除以(a_i!)
    对于单个种类至少有(k)个魔术对的方案就是

    [C(a_i,k)frac{(a_i-1)!}{(a_i-k-1)!} ]

    就是先选择(k)个成为魔术对,再一个一个插入,
    由于剩下的(n-2*k)个不确定是否产生魔术对,所以是至少
    上面这个式子直接表示成(m)个多项式,用分治NTT
    那恰好就不好做了,考虑容斥,

    [ans=sum_{i=k}^n(-1)^{i-k}C(i,k)f[i](n-i)! ]

    ((n-i)!)是因为把剩下的任意排


    代码

    #include <cstdio>
    #include <cctype>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #define rr register
    #define mem(f,n) memset(f,0,sizeof(int)*(n))
    #define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
    using namespace std;
    const int mod=998244353,inv3=332748118,N=100011;
    typedef long long lll; typedef unsigned long long ull;
    int n,m,Gmi[31],Imi[31],len[15],fac[N],inv[N],ff[15][N<<2],a[N],v[15],t=1,ans,k;
    inline signed iut(){
        rr int ans=0; rr char c=getchar();
        while (!isdigit(c)) c=getchar();
        while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
        return ans;
    }
    inline void print(int ans){
        if (ans>9) print(ans/10);
        putchar(ans%10+48);
    }
    inline signed address(){
    	for (rr int i=0;i<15;++i)
        	if (!v[i]) return i;
        return -1;
    }
    inline signed ksm(int x,int y){
    	rr int ans=1;
    	for (;y;y>>=1,x=1ll*x*x%mod)
    	    if (y&1) ans=1ll*ans*x%mod;
    	return ans;
    }
    inline signed C(int n,int m){return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}
    namespace Theoretic{
    	int rev[N<<2],LAST; ull Wt[N<<2],F[N<<2];
    	inline void Pro(int n){
    		if (LAST==n) return; LAST=n,Wt[0]=1;
    		for (rr int i=0;i<n;++i)
    		    rev[i]=(rev[i>>1]>>1)|((i&1)?n>>1:0);
    	}
    	inline void NTT(int *f,int n,int op){
    		Pro(n);
    		for (rr int i=0;i<n;++i) F[i]=f[rev[i]];
    	    for (rr int o=1,len=1;len<n;++o,len<<=1){
    	    	rr int W=(op==1)?Gmi[o]:Imi[o];
    	    	for (rr int j=1;j<len;++j) Wt[j]=Wt[j-1]*W%mod;
    	    	for (rr int i=0;i<n;i+=len+len)
    	    	for (rr int j=0;j<len;++j){
    	    		rr int t=Wt[j]*F[i|j|len]%mod;
    	    		F[i|j|len]=F[i|j]+mod-t,F[i|j]+=t;
    			}
    	    	if (o==10) for (rr int j=0;j<n;++j) F[j]%=mod;
    		}
    		if (op==-1){
    			rr int invn=ksm(n,mod-2);
    			for (rr int i=0;i<n;++i) F[i]=F[i]%mod*invn%mod;
    		}else for (rr int i=0;i<n;++i) F[i]%=mod;
    		for (rr int i=0;i<n;++i) f[i]=F[i];
        }
    	inline void Cb(int *f,int *g,int n){
    		for (rr int i=0;i<n;++i) f[i]=1ll*f[i]*g[i]%mod;
    	}
    	inline signed CDQ_NTT(int l,int r){
    		if (l==r){
    			rr int now=address();
    			len[now]=a[l],v[now]=1;
    			for (rr int i=0;i<len[now];++i)
    				ff[now][i]=1ll*C(a[l],i)*C(a[l]-1,i)%mod*fac[i]%mod;
    			return now;
    		}
    		rr int mid=(l+r)>>1,L;
    		rr int lef=CDQ_NTT(l,mid),rig=CDQ_NTT(mid+1,r);
    		for (L=1;L<len[lef]+len[rig];L<<=1);
    		NTT(ff[lef],L,1),NTT(ff[rig],L,1),Cb(ff[lef],ff[rig],L),
    		mem(ff[rig],L),len[lef]+=len[rig],len[rig]=v[rig]=0,NTT(ff[lef],L,-1);
    		return lef;
    	}
    }
    inline void GmiImi(){
    	for (rr int i=0;i<31;++i) Gmi[i]=ksm(3,(mod-1)/(1<<i));
    	for (rr int i=0;i<31;++i) Imi[i]=ksm(inv3,(mod-1)/(1<<i));		
    }
    signed main(){
    	m=iut(),n=iut(),k=iut(),GmiImi(),inv[0]=inv[1]=fac[0]=fac[1]=1;
    	for (rr int i=2;i<=n;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    	for (rr int i=2;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*inv[i]*inv[i-1]%mod;
    	for (rr int i=1;i<=m;++i) a[i]=iut(),t=1ll*t*inv[a[i]]%mod;
    	rr int now=Theoretic::CDQ_NTT(1,m);
    	for (rr int i=k;i<=n;++i)
    	if ((i-k)&1) ans=(ans+mod-1ll*ff[now][i]*C(i,k)%mod*fac[n-i]%mod)%mod;
    	    else ans=(ans+1ll*ff[now][i]*C(i,k)%mod*fac[n-i]%mod)%mod;
        return !printf("%lld",1ll*ans*t%mod);
    }
    
  • 相关阅读:
    Python--基本的对象类型(列表_可变的数据类型)
    Python--基本的对象类型(数字int和布尔值bool)
    Java项目目录结构
    linux- day1
    python学习笔记,视频day20-装饰器
    python学习笔记,视频day19-习题
    python学习笔记,视频day17、18-文件处理
    python学习笔记,视频day16 17-内置函数
    python学习笔记,视频day16-函数作用域,匿名函数,map,filter,reduce
    python学习笔记,视频day15-全局变量与局部变量、风湿理论、函数递归
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15133170.html
Copyright © 2011-2022 走看看