zoukankan      html  css  js  c++  java
  • [Topcoder 11213] Apple Trees

    题目大意

    数轴上有D个连续整数刻度,有N棵树要种在这些刻度上,其中第i棵与两旁(如果有的话)相邻的树至少要相距Ri,问方法数。
    (1le Dle 10^5,1le N,R_ile 40)

    解析

    我们首先考虑如何去掉 (D) 对复杂度的影响。假如种树的顺序确定为一个排列 (p_{1...n}) ,那么我们只要满足第 (i) 棵树和第 (i+1) 棵树之间的距离大于等于 (max (R_{p_i},R_{p_{i+1}})) 即可,剩下的刻度相当于要放到 (n+1) 个空位里,插板法就能做了。

    假设 (L=sum_{i=1}^{n}max (R_{p_i},R_{p_{i+1}})) ,那么我们对每一个 (L) ,都会剩下 (D-(L-n+1)-n) 个刻度需要插板。我们不妨对每一个 (L) DP得到有多少个排列能够计算得到 (L) 。我们先按照 (R) 从小到大排序,设 (f_{i,j,k}) 表示当前放了前(i) 个数,构成了 (j) 个连续段,此时的总价值为 (k) 的方案数。转移一共有三种情况:

    • 新加进来的数单独构成一个连续段;
    • 新加进来的数将某两个连续段连成了一个;
    • 新的数加在某个连续段的前面或者后面。

    三种情况的转移系数都比较好搞。最后要求的就是 (f_{n,1,L})

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #define N 42
    #define M 200002
    using namespace std;
    const int mod=1000000007;
    int r[N],f[N][N][N*N],fac[M],inv[M];
    int poww(int a,int b)
    {
    	int ans=1,base=a;
    	while(b){
    		if(b&1) ans=1LL*ans*base%mod;
    		base=1LL*base*base%mod;
    		b>>=1;
    	}
    	return ans;
    }
    int C(int n,int m)
    {
    	if(n<0||m<0||n<m) return 0;
    	return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    class AppleTrees{
    public:
    	int theCount(int d,vector<int> a)
    	{
    		int sum=0,n=0,m,ans=0;
    		n=a.size();
    		for(int i=0;i<n;i++) r[i+1]=a[i];
    		sort(r+1,r+n+1);
    		for(int i=1;i<=n;i++) sum=max(sum,r[i]);
    		sum=min(n*sum,d);m=max(sum,d);
    		f[0][0][0]=fac[0]=1;
    		for(int i=1;i<=m+n;i++) fac[i]=1LL*fac[i-1]*i%mod;
    		inv[m+n]=poww(fac[m+n],mod-2);
    		for(int i=m+n-1;i>=0;i--) inv[i]=1LL*inv[i+1]*(i+1)%mod;
    		for(int i=0;i<n;i++){
    			for(int j=0;j<=i;j++){
    				for(int k=0;k<=sum;k++){
    					f[i+1][j+1][k]=(f[i+1][j+1][k]+f[i][j][k])%mod;
    					f[i+1][j-1][k+2*r[i+1]]=(f[i+1][j-1][k+2*r[i+1]]+2LL*C(j,2)*f[i][j][k]%mod)%mod;
    					f[i+1][j][k+r[i+1]]=(f[i+1][j][k+r[i+1]]+2LL*j*f[i][j][k]%mod)%mod;
    				}
    			}
    		}
    		for(int i=0;i<=sum;i++) ans=(ans+1LL*f[n][1][i]*C(d-i+n-1,n)%mod)%mod;
    		return ans;
    	}
    };
    
  • 相关阅读:
    c学习第6天
    c学习第5天
    c学习第4天
    c学习第1天
    20171009/20171010/20171011
    20171010
    20171008
    20171007
    20171006
    matrix
  • 原文地址:https://www.cnblogs.com/LSlzf/p/13966648.html
Copyright © 2011-2022 走看看