• [HAOI2011]Problem c


    2302: [HAOI2011]Problem c

    Description

    给n个人安排座位,先给每个人一个1~n的编号,设第i个人的编号为ai(不同人的编号可以相同),接着从第一个人开始,大家依次入座,第i个人来了以后尝试坐到ai,如果ai被占据了,就尝试ai+1,ai+1也被占据了的话就尝试ai+2,……,如果一直尝试到第n个都不行,该安排方案就不合法。然而有m个人的编号已经确定(他们或许贿赂了你的上司...),你只能安排剩下的人的编号,求有多少种合法的安排方案。由于答案可能很大,只需输出其除以M后的余数即可。


    首先对于每对(,p_i, q_i)显然(p_i)是没有用的

    (f[i][j]) 表示前 (i-n) 个里安排了(j)个的个数

    (v[i])表示编号被钦定(i)的小朋友的个数,(d[i]=sum_1^iv[i])

    [forall jin [v[i],n-i+1] | f[i][j]=sum_{k=0}^{j-v[i]} f[i+1][k]*C_{n-k-d[i]}^{j-k-v[i]} ]


    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define LL long long 
    using namespace std;
    
    int g,i,m,n,j,k,a[100001],t,f[401][401],M,c[401][401],b,v[401],d[401];
    
    int main()
    {
    	scanf("%d",&t);
    	
    	for(;t;t--)
    	{
    		scanf("%d%d%d",&n,&m,&M);
    		memset(v,0,sizeof(v));
    		memset(f,0,sizeof(f));
    		memset(a,0,sizeof(a));
    		for(int i=1;i<=n;i++)	
    		{
    			c[i][i]=c[i][0]=1;
    			for(int j=1;j<i;j++) c[i][j]=((LL)c[i-1][j]+c[i-1][j-1])%M;
    		}
    		for(int i=1;i<=m;i++) scanf("%d%d",&k,&a[i]);
    		sort(a+1,a+1+m); j=1; k=0; b=0;
    		for(int i=1;i<=n;i++) while(a[j]==i) v[i]++, j++; 
    		for(int i=n;i>=1;i--) 
    		{
    			k+=v[i];
    			if(k>n-i+1) {printf("NO
    "); b=1; break;}
    		}
    		if(b) continue;		
    		for(int i=1;i<=n;i++) d[i]=d[i-1]+v[i];
    		g=n-k; f[n+1][0]=1;
    		for(i=n;i>=1;i--)
    			for(j=v[i];j<=n-i+1;j++)
    				for(k=0;k<=j-v[i];k++) f[i][j]=(f[i][j]+(LL)f[i+1][k]*c[n-k-d[i]][j-k-v[i]]%M)%M;
    		
    		printf("YES %d
    ",f[1][n]);
    	}
    }
    
  • 相关阅读:
    bootstrapValidator重新校验/全选回显
    mybatis遍历map参数查询
    location.href传json字符串
    springmvc异步处理
    intellIJ IDEA学习笔记3
    intellIJ IDEA学习笔记2
    intellIJ IDEA学习笔记
    maven国内镜像
    Docker版本Jenkins的使用
    Docker容器网络
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/10197112.html
Copyright © 2020-2023  润新知