zoukankan      html  css  js  c++  java
  • 【CF995F】 Cowmpany Cowmpensation

    CF995F Cowmpany Cowmpensation


    Solution

    这道题目可以看出我的代码能力是有多渣(代码能力严重退化)

    我们先考虑dp,很容易写出方程:

    (f_{i,j})表示以(i)为根的子树中(i)的值为(j),那么转移为:

    [egin{aligned} f_{i,j}=prod_{vin son_u}sum_{k=1}^j{f_{v,j}} end{aligned} ]

    这个东西很明显可以前缀和优化变成(O(n^2))的求解.

    当然不会告诉你我dp写挂了然后身败名裂啊

    发现进一步的优化.

    这个东西如果全用前缀和搞起来不就很像一个函数了?(把每一项出现的拆开考虑)

    emmm,好像是的.

    那么显然这个东西可以通过点值确定这个函数,然后就是喜闻乐见的拉格朗日插值了.

    但是为什么可以成为一个可确定性的函数呢(就是复杂度比较合适).

    考虑叶子节点如果有的话肯定是一次函数.

    emmm,如果深度增加,显然就会高一次.

    深度最大是(n),所以应该只要确定(n)个点就可以了.

    那么就很愉快的写完了.

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<iostream>
    using namespace std;
    #define ll long long
    #define re register
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    #define int ll
    inline int gi()
    {
    	int f=1,sum=0;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    const int N=3010,Mod=1e9+7;
    int dp[N][N],front[N],to[N<<1],nxt[N<<1],cnt,sum[N][N],n,x[N],y[N];
    int Pow(int a,int b)
    {
    	int ret=1;
    	while(b)
        {
    		if(b&1)ret=(ret*a)%Mod;
    		a=(a*a)%Mod;b>>=1;
    	}
    	return ret;
    }
    int lalr(int k)
    {
    	int ans=0;
    	for(int i=1;i<=n;i++)
        {
    		int Up=1,Down=1;
    		for(int j=0;j<=n;j++)
    			if(i!=j)
                {
    				(Up*=(k-x[j]))%=Mod;
    				(Down*=(x[i]-x[j]))%=Mod;
    			}
    		(ans+=(y[i]*Up)%Mod*Pow(Down,Mod-2))%=Mod;
    	}
    	return ans;
    }
    void Add(int u,int v)
    {
    	to[++cnt]=v;nxt[cnt]=front[u];front[u]=cnt;
    }
    void dfs(int u)
    {
    	for(int i=1;i<=n;i++)dp[u][i]=1;
    	for(int i=front[u];i;i=nxt[i])
    	{
    		int v=to[i];
    		dfs(v);
    		for(int j=1;j<=n;j++)
    			dp[u][j]=(ll)dp[u][j]*dp[v][j]%Mod;
    	}
    	for(int i=1;i<=n;i++)
    		dp[u][i]=(dp[u][i]+dp[u][i-1])%Mod;
    }
    void init()
    {
    	dfs(1);	
    }
    signed main()
    {
    	int d;
    	n=gi();d=gi();
    	for(int i=2;i<=n;i++)
    	{
    		int Fa=gi();
    		Add(Fa,i);
    	}
    	init();
    	if(d<=n)return printf("%lld
    ",dp[1][d]),0;
    	for(int i=1;i<=n;i++)x[i]=i,y[i]=dp[1][i];
    	printf("%lld
    ",lalr(d));
    	return 0;
    }
    
  • 相关阅读:
    Leetcode 238. Product of Array Except Self
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 290. Word Pattern
    Leetcode 205. Isomorphic Strings
    Leetcode 107. Binary Tree Level Order Traversal II
    Leetcode 102. Binary Tree Level Order Traversal
    三目运算符
    简单判断案例— 分支结构的应用
    用switch判断月份的练习
    java基本打印练习《我行我素购物系统》
  • 原文地址:https://www.cnblogs.com/mleautomaton/p/10334345.html
Copyright © 2011-2022 走看看