码迷,mamicode.com
首页 > 其他好文 > 详细

[CF995F] Cowmpany Cowmpensation

时间:2021-05-03 12:25:45      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:struct   复杂度   return   register   出现   push   target   容斥   air   

\(\text{Problem}:\)Cowmpany Cowmpensation

\(\text{Solution}:\)

不难发现,虽然权值种类很多,但在一种分配方案中,不同的权值个数只有 \(O(n)\) 个。故设 \(f_{i}\) 表示分配了 \(i\) 种权值的方案数,答案为:

\[\sum\limits_{i=1}^{\min(n,D)}\binom{D}{i}f_{i} \]

难以直接计算求得 \(f_{i}\),故考虑容斥求解。设 \(g_{i}\) 表示分配权值离散化后,最大权值为 \(i\) 的方案数。考虑在剩下的 \(i-1\) 种权值中选出 \(j-1\) 个,即\(f_{j}\)\(g_{i}\) 中会出现 \(\binom{i-1}{j-1}\) 次,要减去 \(f_{j},j<i\)\(f_{i}\) 的贡献。故有:

\[f_{i}=g_{i}-\sum\limits_{j=1}^{i-1}\binom{i-1}{j-1}f_{j} \]

\(g_{i}\) 可以利用树形 \(dp\)\(O(n^2)\) 的时间复杂度内求出。总时间复杂度 \(O(n^2)\)

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=3010, Mod=1e9+7; 
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘) w=-1; ch=getchar(); }
	while(ch>=‘0‘&&ch<=‘9‘) s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,D,g[N][N],f[N];
int fac[N+5],inv[N+5];
inline int ksc(int x,int p) { int res=1; for(;p;p>>=1, x=1ll*x*x%Mod) if(p&1) res=1ll*res*x%Mod; return res; }
inline int C(int x,int y) { if(x<y||x<0||y<0) return 0; return 1ll*fac[x]*inv[x-y]%Mod*inv[y]%Mod; }
int head[N],maxE; struct Edge { int nxt,to; }e[N];
inline void Add(int u,int v) { e[++maxE].nxt=head[u]; head[u]=maxE; e[maxE].to=v; }
void DFS(int x)
{
	for(ri int i=1;i<=n;i++) g[x][i]=1;
	for(ri int i=head[x];i;i=e[i].nxt)
	{
		int v=e[i].to;
		DFS(v);
		for(ri int j=1;j<=n;j++) g[x][j]=1ll*g[x][j]*g[v][j]%Mod;
	}
	for(ri int i=1;i<=n;i++) g[x][i]=(g[x][i-1]+g[x][i])%Mod;
}
signed main()
{
	fac[0]=1;
	for(ri int i=1;i<=N;i++) fac[i]=1ll*fac[i-1]*i%Mod;
	inv[N]=ksc(fac[N],Mod-2);
	for(ri int i=N;i;i--) inv[i-1]=1ll*inv[i]*i%Mod;
	n=read(), D=read();
	for(ri int i=1;i<n;i++)
	{
		int x=read();
		Add(x,i+1);
	}
	DFS(1);
	for(ri int i=1;i<=n;i++)
	{
		f[i]=(g[1][i]-g[1][i-1]+Mod)%Mod;
		for(ri int j=1;j<i;j++)
		{
			int w=1ll*C(i-1,j-1)*f[j]%Mod;
			f[i]=(f[i]-w+Mod)%Mod;
		}
	}
	int ans=0;
	for(ri int i=1,now=D;i<=n&&i<=D;i++) ans=(ans+1ll*now*inv[i]%Mod*f[i]%Mod)%Mod, now=1ll*now*(D-i)%Mod;
	printf("%d\n",ans);
	return 0;
}

[CF995F] Cowmpany Cowmpensation

标签:struct   复杂度   return   register   出现   push   target   容斥   air   

原文地址:https://www.cnblogs.com/zkdxl/p/14723801.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!