zoukankan      html  css  js  c++  java
  • Codeforces F. Cowmpany Cowmpensation

    Description

    有一棵树,现在要给每个节点赋一个在1到D之间的权值,问有多少种方案满足任意一个节点的权值都不大于其父亲的权值。
    n<=3000,D<=1e9
    题面

    Solution

    容易发现 (f(D)) 是一个 (n) 次多项式.
    求出 (f(1),f(2),...,f(n+1)) 之后拉格朗日插值即可.

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3010,mod=1e9+7;
    int n,m,head[N],to[N*2],nxt[N*2],fa[N],num=0,f[N][N],inv[N];
    inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
    inline void dfs(int x){
    	for(int i=1;i<=n+1;i++)f[x][i]=1;
    	for(int i=head[x],u;i;i=nxt[i]){
    		if((u=to[i])==fa[x])continue;
    		dfs(u);
    		int sum=0;
    		for(int j=1;j<=n+1;j++){
    			sum=(sum+f[u][j])%mod;
    			f[x][j]=1ll*f[x][j]*sum%mod;
    		}
    	}
    }
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      cin>>n>>m;
      for(int i=2;i<=n;i++)cin>>fa[i],link(fa[i],i);
      dfs(1);
      for(int i=2;i<=n+1;i++)f[1][i]=(f[1][i]+f[1][i-1])%mod;
      if(m<=n+1)cout<<f[1][m],exit(0);
      inv[0]=inv[1]=1;
      for(int i=2;i<=n;i++)inv[i]=(mod-1ll*(mod/i)*inv[mod%i]%mod)%mod;
      int ans=0;
      for(int i=1;i<=n+1;i++){
    	  int t=1;
    	  for(int j=1;j<=n+1;j++){
    		  if(i==j)continue;
    		  t=1ll*t*(m-j)%mod*(i>=j?inv[i-j]:-inv[j-i])%mod;
    	  }
    	  ans=(ans+1ll*t*f[1][i])%mod;
      }
      cout<<(ans+mod)%mod;
      return 0;
    }
    
    
  • 相关阅读:
    腾讯//全排列
    腾讯//全排列
    腾讯//子集
    腾讯//子集
    腾讯///括号生成
    腾讯///括号生成
    腾讯//二叉树的最近公共祖先
    腾讯//二叉树的最近公共祖先
    腾讯//二叉搜索树的最近公共祖先
    腾讯//二叉搜索树的最近公共祖先
  • 原文地址:https://www.cnblogs.com/Yuzao/p/9270626.html
Copyright © 2011-2022 走看看