• [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
    ", 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] = egin{cases} frac{(sz[x] - 1)!}{prod_{i in{ch(x)}}{sz[i]!}} imes 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
    ", g[i]);
    	return 0;
    }
    
  • 相关阅读:
    Ubuntu安装vmtools后,Window无法向其复制文件
    Tomcat弱密码导致getshell
    免杀工具 FourEye
    ubuntu 安装docker
    做有追求的程序员
    nrm 源切换工具 Jim
    url加载图片,如何判断加载成功 Jim
    vue实现文件流预览pdf Jim
    将日期格式转换成时间戳 Jim
    js如何实现多线程之web worker Jim
  • 原文地址:https://www.cnblogs.com/LJB00131/p/12590040.html
Copyright © 2020-2023  润新知