• [CF995F]Cowmpany Cowmpensation


    codeforces

    description

    一棵(n)个节点的树,给每个节点标一个([1,m])之间的编号,要求儿子的权值不大于父亲权值。求方案数。(nle3000,nle10^9)

    sol

    可以证明答案是关于(m)的一个(n)次多项式。我不会证。
    如果(P(x))是关于(x)(n)次多项式,则有

    [P(x)=sum_{i=0}^{n}(-1)^{n-i}P(i)frac{x(x-1)...(x-n)}{(n-i)!i!(x-i)} ]

    可见杜教(mbox{PPT})《多项式与求和》。
    所以只要对([1,n])求答案就可以了,很显然是一个(O(n^2))(dp),所以复杂度是(O(n^2))

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 3005;
    const int mod = 1e9+7;
    int n,m,nxt[N],head[N],f[N][N],inv[N],ans;
    void dfs(int u){
    	for (int i=1;i<=n;++i) f[u][i]=1;
    	for (int v=head[u];v;v=nxt[v]){
    		dfs(v);
    		for (int i=1;i<=n;++i)
    			f[u][i]=1ll*f[u][i]*f[v][i]%mod;
    	}
    	for (int i=2;i<=n;++i) (f[u][i]+=f[u][i-1])%=mod;
    }
    int main(){
    	n=gi();m=gi();inv[0]=inv[1]=1;
    	for (int i=2;i<=n;++i) inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
    	for (int i=2,ff;i<=n;++i)
    		nxt[i]=head[ff=gi()],head[ff]=i;
    	dfs(1);
    	if (m<=n) return printf("%d
    ",f[1][m]),0;
    	for (int i=1;i<=n;++i){
    		int sum=f[1][i];
    		for (int j=0;j<=n;++j)
    			if (j!=i) sum=1ll*sum*(m-j)%mod*(i>j?inv[i-j]:mod-inv[j-i])%mod;
    		(ans+=sum)%=mod;
    	}
    	printf("%d
    ",ans);return 0;
    }
    
  • 相关阅读:
    mybatis(十)缓存
    mybatis(八)复杂查询
    mybatis(六)分页
    mybatis(九)动态SQL
    mybatis(七)只用注解开发
    mybatis(五) 日志
    log4j.properties 相关配置
    mybatis(四)中可能出现的问题
    MyBatis(三) 配置解析
    IIS 发布 .net core 3.1
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9387662.html
Copyright © 2020-2023  润新知