[ABC160] 题解

由于是ABC, 所以ABC题过于简单就咕咕咕了

D Line++

枚举一下所有组判断一下即可

#include<bits/stdc++.h>

using namespace std;

int n, x, y, ans[10005];

int main()
{
	cin >> n >> x >> y;
	for(int i = 1; i <= n; i++)
	{
		for(int j = i + 1; j <= n; j++)
		{
			int t = min(min(j - i, abs(x - i) + abs(j - x)), min(abs(y - i) + abs(j - y), abs(x - i) + 1 + abs(j - y)));
			ans[t]++;
		}
	}
	for(int i = 1; i <= n - 1; i++)
		printf("%d\n", ans[i]);
	return 0;
}

E Red and Green Apples

显然从大到小排好序后最优,无色的苹果不用管它,因为只要你取到个数且不超过限制一定可以通过分配使他满足。(所以代码特别好写)

#include<bits/stdc++.h>

using namespace std;

#define N 500005

int a, b, c, n, X, Y;

long long ans = 0;

struct point
{
	int v, id;

	bool operator < (const point &o) const
	{
		return v > o.v;
	}
}p[N];

int main()
{
	ios::sync_with_stdio(false);
	cin >> X >> Y >> a >> b >> c;
	n = a + b + c;
	for(int i = 1; i <= n; i++)
	{
		cin >> p[i].v;
		if(i <= a) p[i].id = 1;
		else if(i <= a + b) p[i].id = 2;
		else p[i].id = 3; 
	}
	sort(p + 1, p + n + 1);
	int x = 0, y = 0, cnt = 0;
	for(int i = 1; i <= n; i++)
	{
		if(p[i].id == 1)
		{
			if(x == X) continue;
			else x++;
		}
		else if(p[i].id == 2)
		{
			if(y == Y) continue;
			else y++;
		}
		ans += 1ll * p[i].v;
		cnt++;
		if(cnt == X + Y) break;
	}
	cout << ans << endl;
	return 0;
}

F Distributing Integers

来填坑了

赛时没切掉 /kk 我发现我并不会多重集的排列这个东西。

简单介绍一下,令 \(S\)\(k\) 种不同类型对象(每种集合里的对象等价)的多重集合,从S中取r个数构成排列的方案数称为 \(S\)\(r\) 排列。当 \(r = n\) 时,有
\(P(n, n_1*a_1, ..., n_k*a_k) = \frac{(n - 1)!}{\prod_{i = 1}^{k}n_k!}\)

回到这道题,我们首先取1为根,做一遍树形dp, 令 \(f[i]\) 表示以i为根的树有多少种填数字的方案。

\[f[x] = \begin{cases} \frac{(sz[x] - 1)!}{\prod_{i \in{ch(x)}}{sz[i]!}} \times \prod_{i \in{ch(x)}}{f[i]} , sz[x] > 1 \\ 1, sz[x] = 1 \end{cases} \]

是叶子结点就是1, 不是叶子结点就是我把每个子树看做一个集合做多重集排列(得出顺序), 然后直接乘每个每个子树的贡献就行。

做完第一次树形dp之后进行换根dp,这一步应该比较简单,只要每次换的时候消除/加入影响即可

#include<bits/stdc++.h>

using namespace std;

#define N 200005
const int mod = 1e9 + 7;
#define add(x, y) (x + y >= mod ? x + y - mod : x + y)
#define dec(x, y) (x < y ? x - y + mod ? x - y)

int n, a[N], head[N], nxt[N << 1], to[N << 1], cnt = 0, sz[N], f[N], fac[N], inv[N], g[N];

int Pow(int x, int k)
{
	int base = x, ans = 1;
	while(k)
	{
		if(k & 1) ans = 1ll * ans * base % mod;
		base = 1ll * base * base % mod;
		k >>= 1;
	}
	return ans;
}

void adde(int x, int y)
{
	cnt++;
	to[cnt] = y;
	nxt[cnt] = head[x];
	head[x] = cnt;
}

void dfs(int x, int fa)
{
	sz[x] = 1;
	for(int p = head[x]; p; p = nxt[p])
	{
		int v = to[p];
		if(v == fa) continue;
		dfs(v, x);
		sz[x] += sz[v];
	}
	f[x] = fac[sz[x] - 1];
	for(int p = head[x]; p; p = nxt[p])
	{
		int v = to[p];
		if(v == fa) continue;
		f[x] = 1ll * f[x] * inv[sz[v]] % mod * f[v] % mod; 
	}
}

void dfs2(int x, int fa)
{
	for(int p = head[x]; p; p = nxt[p])
	{
		int v = to[p];
		if(v == fa) continue;
		int t = 1ll * g[x] * fac[n - 1 - sz[v]] % mod * inv[n - 1] % mod * fac[sz[v]] % mod * Pow(f[v], mod - 2) % mod;
		int ns = n - sz[v];
		// cout << x << ' ' << v << ' ' << t << ' ' << ns << endl;
		g[v] = 1ll * f[v] * t % mod * inv[ns] % mod * fac[n - 1] % mod * inv[sz[v] - 1] % mod;
		dfs2(v, x);
	}
}

int main()
{
	scanf("%d", &n);
	for(int i = 1; i <= n - 1; i++)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		adde(x, y), adde(y, x);
	}
	fac[0] = 1, inv[0] = 1, fac[1] = 1, inv[1] = 1;
	for(int i = 2; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % mod, inv[i] = Pow(fac[i], mod - 2);
	dfs(1, 1);
	// cout << f[1] << endl;
	g[1] = f[1];
	dfs2(1, 1);
	for(int i = 1; i <= n; i++)
		printf("%d\n", g[i]);
	return 0;
}
posted @ 2020-03-28 22:53  LJB00131  阅读(211)  评论(2编辑  收藏  举报