• 计蒜客信息学赛前 CSP-S2 模拟赛 2


    本来想打打计蒜客的比赛涨涨信心的,结果(T2)少考虑了一点东西给我整自闭了。

    (A)

    按位与的性质是,(a & b <= a),所以某个点的距离就是所有直接与它相连的边的边权。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 1000000;
    
    int n, head[N + 50], num, dp[N + 50];
    
    template <class T>
    void Read(T &x)
    {
    	x = 0; int p = 0; char st = getchar();
    	while (st < '0' || st > '9') p = (st == '-'), st = getchar();
    	while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
    	x = p ? -x : x;
    	return;
    }
    
    template <class T>
    void Print(T x)
    {
    	if (x > 9) Print(x / 10);
    	putchar(x % 10 + '0');
    	return;
    }
    
    void File()
    {
    	freopen("node.in", "r", stdin);
    	freopen("node.out", "w", stdout);
    	return;
    }
    
    struct Node
    {
    	int next, to, dis;
    } edge[N * 2 + 50];
    
    void Addedge(int u, int v, int w)
    {
    	edge[++num] = (Node){head[u], v, w};
    	head[u] = num;
    	return;
    }
    
    void Dfs(int x, int fa, int fadis)
    {
    	int maxx = fadis;
    	for (int i = head[x]; i; i = edge[i].next)
    	{
    		int v = edge[i].to;
    		if (v == fa) continue;
    		maxx = max(maxx, edge[i].dis);
    		Dfs(v, x, edge[i].dis);
    	}
    	dp[x] = maxx;
    	return;
    }
    
    int main()
    { 
    //	File();
    	Read(n);
    	for (int i = 1, u, v, w; i <= n - 1; i++)
    	{
    		Read(u); Read(v); Read(w);
    		Addedge(u, v, w); Addedge(v, u, w);
    	}
    	Dfs(1, 0, 0);
    	int pos = 1;
    	for (int i = 2; i <= n; i++) if (dp[i] < dp[pos]) pos = i;
    	printf("%d", pos);
    	return 0;
    }
    

    (B)

    考虑只有(> k)(n - k)个点会对答案产生影响,所以令(m - n - k),将这(m)个点和剩下(k)个点分开来讨论。

    定义一段连续的放在一起的(> k)的点为连通块,那么最后删去的边的数量就是(n - k -)连通块个数。

    这样就可以枚举连通块个数算算贡献。

    当把这(m)个点分成若干块时,剩下的(k)个点也需要分成(k)块,所以最多可以分成(min(k, m - d))块。

    枚举最后分成的块数(p),那么先用隔板法分成若干个集合(inom{m - 1}{p - 1})(inom{k - 1}{p - 1}),再枚举集合内部的情况乘上(m!)(k!)

    然后因为环上的每个位置是不同的,所以再枚举哪个数开头将答案( imes n)

    但是发现之前划分集合的时候,因为集合是没有区分的,所以每种方案一共算了(p)次,答案要除以(p)

    这样最后就是

    [sum_{p = 1}^{min(k, m - d)} frac{inom{m - 1}{p - 1} inom{k - 1}{p - 1} imes m! imes k! imes n}{p} ]

    考试的时候就差了最后除以(p)那一步,难受。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 1000000;
    const int MOD = 998244353;
    
    template <class T>
    void Read(T &x)
    {
    	x = 0; int p = 0; char st = getchar();
    	while (st < '0' || st > '9') p = (st == '-'), st = getchar();
    	while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
    	x = p ? -x : x;
    	return;
    }
    
    template <class T>
    void Print(T x)
    {
    	if (x > 9) Print(x / 10);
    	putchar(x % 10 + '0');
    	return;
    }
    
    int jc[N + 50], divjc[N + 50], n, k, d, div[N + 50];
    
    int Zh(int n, int m)
    {
    	return 1LL * jc[n] * divjc[n - m] % MOD * divjc[m] % MOD;
    }
    
    int Ksm(int a, int b)
    {
    	int tmp = 1;
    	while (b)
    	{
    		if (b & 1) tmp = 1LL * tmp * a % MOD;
    		a = 1LL * a * a % MOD;
    		b >>= 1;	
    	} 
    	return tmp;
    }
    
    void File()
    {
    	freopen("ring.in", "r", stdin);
    	freopen("ring.out", "w", stdout);
    	return;
    }
    
    int main()
    {
    //	File();
    	int t;
    	Read(t);
    	jc[0] = 1;
    	for (int i = 1; i <= N; i++) jc[i] = 1LL * jc[i - 1] * i % MOD;
    	divjc[N] = Ksm(jc[N], MOD - 2);
    	for (int i = N - 1; i >= 0; i--) div[i + 1] = 1LL * divjc[i + 1] * jc[i] % MOD, divjc[i] = 1LL * divjc[i + 1] * (i + 1) % MOD;
    	divjc[0] = div[0] = 1;
    	while (t--)
    	{
    		Read(n); Read(k); Read(d);
    		int m = n - k, ans = 0;
    		for (int i = 1; i <= m - d; i++)
    			ans = (0LL + ans + 1LL * Zh(m - 1, i - 1) * Zh(k, i - 1) % MOD * div[i] % MOD) % MOD;
    		ans = 1LL * ans * n %MOD * jc[m] % MOD * jc[k] % MOD;
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
    /*
    1
    4 2 1
    
    16
    */
    

    (C)

    (D)

  • 相关阅读:
    JavaScript手把手教你写出令人窒息的烂代码
    查询数据库表名,数据表信息,MySQL Key值(PRI, UNI, MUL)的含义
    【转载】 世界读书日:来自李开复的六个读书建议
    安装python库roboschool运行报错:ImportError: libpcre16.so.3: cannot open shared object file——解决方法
    Python 二次开发 AutoCAD 简介
    MATLAB元胞数组删除一个元素
    英语单词积累
    一战后德国要支付1320亿金马克的赔款,都按期足额付完了吗
    cad无级缩放
    [转]mysql导入数据load data infile用法
  • 原文地址:https://www.cnblogs.com/Tian-Xing-Sakura/p/13836696.html
Copyright © 2020-2023  润新知