zoukankan      html  css  js  c++  java
  • [HZOI 2016]我们爱数数

    [HZOI 2016]我们爱数数

    题目大意:

    一张圆桌,每个位置按顺时针从(1)(n)编号。有(n)个人,编号从(1)(n)。如果编号为(i)的人坐到了编号为(i)的位置或坐到了与编号为(i)的位置相邻的位置,这个人就会感到开心,反之这个人会感到沮丧。求有多少种安排坐位的方法,使所有人都入座,并且使得至少(k)个人开心。

    思路:

    (f_{i,j,s})表示前(i)个人,(j)个人开心,目前最后两个位置的状态为(s)的方案数。

    枚举前两个人的位置,就可以化环为链,直接DP就可以求出(f)的值。

    (g_i)表示((n-i)!sum f_{i,j,s})(g_i=sum {jchoose i}ans_j)。故(ans)可以通过(g_i)推出。

    参考题解

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    typedef long long int64;
    const int N=1001;
    const int mod=1e9+7;
    int p1[4]={0,0,1,2},p2[4]={0,1,2,3};
    int n,m,fac[N],ifac[N],f[N][N][4],g[N];
    bool v[N];
    void exgcd(const int &a,const int &b,int &x,int &y) {
    	if(!b) {
    		x=1,y=0;
    		return;
    	}
    	exgcd(b,a%b,y,x);
    	y-=a/b*x;
    }
    inline int inv(const int &x) {
    	int ret,tmp;
    	exgcd(x,mod,ret,tmp);
    	return ((ret%mod)+mod)%mod;
    }
    inline int C(const int &n,const int &m) {
    	if(m>n) return 0;
    	return (int64)fac[n]*ifac[m]%mod*ifac[n-m]%mod;
    }
    int main() {
    	n=p1[1]=getint(),m=getint();
    	for(register int i=fac[0]=1;i<=n;i++) {
    		fac[i]=(int64)fac[i-1]*i%mod;
    	}
    	ifac[n]=inv(fac[n]);
    	for(register int i=n;i>=1;i--) {
    		ifac[i-1]=(int64)ifac[i]*i%mod;
    	}
    	for(register int i=0;i<4;i++) {
    		const int &a=p1[i];
    		v[a]=true;
    		for(register int j=0;j<4;j++) {
    			const int &b=p2[j];
    			if(a&&b&&a==b) continue;
    			v[b]=true;
    			memset(f,0,sizeof f);
    			f[2][(!!a)+(!!b)][(v[3]<<1)|v[2]]=1;
    			for(register int i=2;i<n;i++) {
    				for(register int j=0;j<=i;j++) {
    					for(register int k=0;k<4;k++) {
    						if(!f[i][j][k]) continue;
    						(f[i+1][j][k>>1]+=f[i][j][k])%=mod;
    						(f[i+1][j+1][2+(k>>1)]+=f[i][j][k])%=mod;
    						if(!(k&1)) (f[i+1][j+1][k>>1]+=f[i][j][k])%=mod;
    						if(!((k>>1)&1)) (f[i+1][j+1][1]+=f[i][j][k])%=mod;
    					}
    				}
    			}
    			const int t=((v[1]<<1)+v[n]);
    			for(register int i=1;i<=n;i++) {
    				for(register int k=0;k<4;k++) {
    					if(k&t) continue;
    					(g[i]+=(int64)f[n][i][k]*fac[n-i]%mod)%=mod;
    				}
    			}
    			v[b]=false;
    		}
    		v[a]=false;
    	}
    	for(register int i=n;i;i--) {
    		for(register int j=i+1;j<=n;j++) {
    			g[i]=((g[i]-(int64)g[j]*C(j,i)%mod)%mod+mod)%mod;
    		}
    	}
    	int ans=0;
    	for(register int i=m;i<=n;i++) (ans+=g[i])%=mod;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Innodb之线程独享内存
    Innodb之全局共享内存
    mysql三层体系
    grep/字符/次数匹配/锚定符/小大括号/wc/tr/cut/sort/uniq
    Mysql多字段模糊查询
    小程序中使用less(最优方式)
    js控制文本框只能输入中文、英文、数字与指定特殊符号
    连接 MySQL 数据库出现问题:The server time zone value ‘�й���׼ʱ��‘ is unrecogni....
    Mysql聚簇索引和非聚簇索引
    npm run dev 和 npm run serve
  • 原文地址:https://www.cnblogs.com/skylee03/p/9365444.html
Copyright © 2011-2022 走看看