• Jzoj3497 隐藏指令


    题意:求在n维空间里,长度为2m且起点和终点重合的简单路径(只能在一维中走)数量

    显然,我们在计算方案时,每次必然加入在同一维度的,方向相反的行动

    那么我们令f[i][j][k]表示目前在处理第i维,已经走了2*j步,其中有2*k步在第i维上

    那么显然,f[i+1][j][0]+=f[i][j][k] 这等于是停止当前这一维的处理,开始下一维

    那么另一种转移是这样滴

    f[i][j+1][k+1]+=f[i][j][k]*C(k+1<<1,k+1)/C(k<<1,k)*C(j+1<<1,k+1<<1)/C(j<<1,k<<1)

    表示的是,在这一维加入一对相反的行动,那么,显然,在这一维里面,正反都是一样的

    所以对于同一维中,若有2k步,我们有C(2k,k)排序方案,这点很显然因为这相当于在长度为2k的空格中插入k个0和k个1,那么方案自然是C(2k,k),那么我们先除去上一次的方案再乘上我们新加入的方案

    而对于不同维度,互相不影响,所以相当于是把2k个对象放入长度为2j的数组中,那么这样的方案就有C(2j,2k)

    所以f[i][j+1][k+1]+=f[i][j][k]*C(k+1<<1,k+1)/C(k<<1,k)*C(j+1<<1,k+1<<1)/C(j<<1,k<<1),先除去当前状态的影响再加入新的元素重新计算

    而组合数乘除可以用逆元预处理,最后答案为Σf[d][n][k] (0<=k<=n)

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define L long long
    #define M 1000000007
    using namespace std;
    inline L pow(L x,int k){
    	L s=1;
    	for(;k;x=x*x%M,k>>=1)
    		if(k&1) s=s*x%M;
    	return s;
    }
    inline void ad(L& x,L y){ x=(x+y)%M; }
    L js[510],inv[510],A=0,f[210][210][210];
    inline L C(int n,int m){ return js[n]*inv[m]%M*inv[n-m]%M; }
    inline L gC(int n,int m){ return inv[n]*js[m]%M*js[n-m]%M; }
    int main(){
    	*js=*inv=1;
    	for(int i=1;i<=500;++i) js[i]=js[i-1]*i%M;
    	inv[500]=pow(js[500],M-2);
    	for(int i=500;i;--i) inv[i-1]=inv[i]*i%M;
    	int n,d; scanf("%d%d",&d,&n); f[1][0][0]=1;
    	for(int i=1;i<=d;++i)
    		for(int j=0;j<=n;++j)
    			for(int k=0;k<=j;++k)
    				if(f[i][j][k]){
    					ad(f[i+1][j][0],f[i][j][k]);
    					ad(f[i][j+1][k+1],f[i][j][k]*C(k+1<<1,k+1)%M*gC(k<<1,k)%M*C(j+1<<1,k+1<<1)%M*gC(j<<1,k<<1)%M);
    				}
    	for(int k=0;k<=n;++k) ad(A,f[d][n][k]);
    	printf("%lld
    ",A);
    }


  • 相关阅读:
    C语言I博客作业04
    C语言II博客作业04
    C语言II作业03
    C语言II博客作业02
    C语言II博客作业01
    第一周C语言作业
    C语言I博客作业02
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/7774410.html
Copyright © 2020-2023  润新知