• 2022717 #14 uoj424


    每次 CF 都被中国场爆杀

    今天模拟赛 MLE 了一题怒挂 80,又垫底了。。。

    038 uoj#424. 【集训队作业2018】count

    建出笛卡尔树,那么每个点到根节点的左儿子边数量不能超过 \(m\),因为向左走一步权值必须减一。

    逆用兄弟儿子表示法,问题变为计数深度不超过 \(m\),节点数量为 \(n\),儿子有顺序的多叉树数量。

    这里考虑生成函数并不是一个很好的选择,原因是深度实际上与儿子有顺序的多叉树括号序列有着较大的关系,我们不应将两维分开考虑。

    考察其括号序列,左括号对应右上步,右括号对应右下步,即计数使用右上、右下步,从 \((0,0)\) 走到 \((2n,0)\),不越过 \(y=0\)\(y=m\) 的格路数量。

    两条直线的限制的格路行走是经典问题,反射容斥即可解决。

    #include<stdio.h>
    const int maxn=200005,mod=998244353;
    int n,m,ans;
    int fac[maxn],inv[maxn],nfac[maxn];
    inline int C(int a,int b){
    	return a<b||b<0? 0:1ll*fac[a]*nfac[b]%mod*nfac[a-b]%mod;
    }
    int calc(int y){//(0,0) (2n,y)
    	return C(n+n,n+y/2);
    }
    int main(){
    	fac[0]=fac[1]=nfac[0]=nfac[1]=inv[1]=1;
    	for(int i=2;i<maxn;i++)
    		fac[i]=1ll*fac[i-1]*i%mod,inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod,nfac[i]=1ll*nfac[i-1]*inv[i]%mod;
    	scanf("%d%d",&n,&m);
    	if(n<m){
    		puts("0");
    		return 0;
    	}
    	ans=calc(0);
    	for(int y=0;y>=-n-n&&y<=n+n;){
    		y=-2-y,ans=(ans-calc(y)+mod)%mod;
    		y=2*(m+1)-y,ans=(ans+calc(y))%mod;
    	}
    	for(int y=0;y>=-n-n&&y<=n+n;){
    		y=2*(m+1)-y,ans=(ans-calc(y)+mod)%mod;
    		y=-2-y,ans=(ans+calc(y))%mod;
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    Solr服务在Linux上的搭建详细教程
    Linux服务器上安装JDK小白教程
    request和response中文乱码问题后台处理办法
    Redis的五种数据类型及方法
    Java类装载器ClassLoader
    Git快速入门和常用命令
    redis在Linux上的部署和jedis简单使用
    Linux常用基础命令
    JDK1.7中HashMap底层实现原理
    微信电脑版无法显示图片无法下载文件
  • 原文地址:https://www.cnblogs.com/xiaoziyao/p/16488609.html
Copyright © 2020-2023  润新知