• YAOI Round #1 (Div.2) 题解


    总体来说很有一定区分度的(主要分为 4 题、2 题、1 题几档),ACM 赛制也挺有意思的,征求一下大家对这场比赛的意见吧,可以在这个帖子下回复,我都会看的。

    简要题解:(

    A. 云之彼端,约定的地方

    解法:

    本题是拓扑学中的欧拉公式的结论题。

    我们发现 (V=E-F+2) ,于是便得到了答案。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main()
    {
          int e,f;
          scanf("%d%d",&e,&f);
          printf("%d",e-f+2);
          return 0;
    }
    

    B. 秒速 5 厘米

    考点: 欧几里得法,裴蜀定理,简单数论/构造。近年来考试对数论的考察(如17、18年)都有所加深,今年更是考了一道构造题。

    题解: 要使所有的数清零,也就是要使方程 (len1 imes x + len2 imes y + len3 imes z + X = 0) 这个方程一定有解。联想到裴蜀定理:(ax+by=c)有解当且仅当 (gcd(x,y) | c),当 (a)(b) 互质的时候这个方程一定有解。所以我们第一次操作修改 (1)$n$,第二次修改$1$(n-1),第三次修改(n)。由于 (n)(n-1) 互质,前两次一定存在方法使两次之和加上原数等于 (0),而最后一次操作能使最后一个数清零。

    具体构造方案就变成了解方程 (nx + (n-1)y = C) 的任意一组解,不管是交给小学奥数还是交给拓展欧几里得都是可以的。

    这题的构造其实不难想到,当然观察样例也可以发现,可以说观察样例是极其重要的能力。

    标程: (来自 liyiming,我自己是用拓欧写的,放这个比较友好。)

    int main() {
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        cout << 1 << " " << n - 1 << endl;
        cout << a[1] * (n - 1);
        for (int i = 2; i <= n - 1; i++) cout << " " << a[i] * (n - 1);
        cout << endl;
        cout << 1 << " " << n << endl;
        for (int i = 1; i <= n - 1; i++) cout << -a[i] * n << " ";
        cout << 0 << endl;
        cout << n << " " << n << endl;
        cout << -a[n];
        cout << endl;
        return 0;
    }
    

    C. 追逐繁星的孩子

    解法:

    对于这棵树,从 (1) 号节点开始进行一次 ( ext{dfs}) ,并在过程中计算经过该点的概率即可。

    当然,如果当前概率已经不合法,则可以剪枝优化。

    代码:

    #include <bits/stdc++.h>
    #define Re register
    using namespace std;
     
    const int maxn=500005;
    vector<int> T[maxn],E[maxn];
    int n,q,cnt;
    
    void dfs(int x,int fa,long double p)
    {
    	if(p*100<q) return;
    	cnt++;
    	for(Re int i=0;i<T[x].size();i++)
    	{
    		if(T[x][i]==fa) continue;
    		dfs(T[x][i],x,p*E[x][i]/100);
    	}
    }
    
    int main()
    {
    	scanf("%d%d",&n,&q);
    	for(Re int i=1;i<n;i++)
    	{
    		int u,v,p;
    		scanf("%d%d%d",&u,&v,&p);
    		T[u].push_back(v);
    		T[v].push_back(u);
    		E[u].push_back(p);
    		E[v].push_back(p);
    	}
    	dfs(1,1,1.0);
    	printf("%d",cnt);
    	return 0;
    }
    

    D. 言叶之庭

    标程:

    int n; cin >>n;
    for (int i = n - 1; i >= 0; i--)
    {
        f[i] = f[i+1] + (double)n / ((double)n - i);
        g[i] = g[i+1] + (double)i / ((double)n - i) * f[i]+ f[i+1] + (double)n / ((double)n - i);
    }
    printf("%.2lf",g[0]);
    

    考点: 期望相关知识,可以说期望是一个大难点,如何逾越它是个重要的问题。

    题解: 这题的期望还是很巧妙的。

    (f_{i}) 表示已经买到了 (i) 张不同的邮票的期望步数,(g_{i}) 表示表示已经买到了 (i) 张不同的邮票的期望花费;(h_{i}) 表示已经买到了 (i) 张不同的邮票、想买下剩下邮票的期望步数,(y_{i}) 表示表示已经买到了 (i) 张不同的邮票、想买下剩下邮票的期望花费。

    我们可以得到一些好玩的式子们,有一些是对的,有一些是错的:

    [f_i = f_{i-1} + frac{n}{n-i+1} ]

    这个式子是对的,为什么呢?我抽到新邮票的概率是 (frac{n-i+1}{n}),那么抽到新邮票的期望次数就是 (frac{n}{n-i+1})。上述式子甚至可以写成 $ f_n = sumlimits { frac{1}{i} } $。

    [g_n = frac{f_n(f_n+1)}{2} ]

    这个式子显然是错的。为什么呢?有两种解释方法,一是每种 (f_n) 的取值的贡献不是一样的,不满足线性性;也可以看做是 (mathbb{E}(x^2)) 作为不独立的两个变量相乘,不具有线性性。

    [g_i = g_{i-1} + f_i imes frac{n}{n-i+1} ]

    这个式子又是对的了,这个成立就能得到一些很好玩的式子,比如 $ f_{n} = sumlimits_{i=1}^{n}(frac{n}{i} sumlimits_{j=1}^{i}(frac{n}{i})) $。

    [h_i = frac{i}{n}(h_i + 1) + frac{n-i}{n}(h_{i+1} + 1) ]

    这个来源于分类讨论,两种情况分别讨论一下,移项一下就能得到递推式。

    [y_i = frac{i}{n}(h_i+y_i+1) + frac{n-i}{n}(h_{i+1}+y_i+1) ]

    和上面的方程的来源是一样的,但是需要用到费用提前计算——(h_i+1) 的含义是替后面的提前加上。但这个式子还是有一些难以解释通的地方,为什么递归下去后每次提前计算的贡献是相同的?那不是成了平行四边形吗?这个方法使得期望满足了线性性——竖着我统计没有线性性,横过来看就能巧妙地去掉乘积项,就拥有了线性性。

    更为不严谨的方程: 设买了 (x) 次邮票,答案就是 (frac{x+x^2}{2})。设 (w_i) 表示已经买到了 (i) 种邮票、要买剩下的的邮票的次数平方的期望(注意和期望的平方的区别),那么可以得到

    [w_i = frac{i}{n}(w_i + 2h_i + 1) + frac{n-i}{n}(w_{i+1} + 2h_{i+1} + 1) ]

    于是答案就是 (frac{h_0 + w_0}{2})。但是——这么做是有问题的——因为默认了平方的期望等于期望的平方!但是,他居然是对的!错的做法能过,说明过的做法都是错的,细思极恐啊!

    E. 你的名字

    考点: 组合数学,计数问题。计数问题是福建省选的黄金考点,六题能出四道计数。

    题解: 使用 Burnside 引理((cnt = frac{1}{|G|}sumlimits chi (x)))或者简单的容斥可得 (ans=frac{2 imes 2^{frac{n^2}{4}} + 2^{frac{n^2}{2}} + 2^{n^2}}{4}),下面讨论如何计算这个值。

    2 的那么多次方可以使用快速幂计算;由于指数远远超出了 long long 范畴,所以考虑怎么把指数变小。由费马小定理得 (2^{p-1} equiv 1 (mod p)),所以 (2^{k} equiv 2^{k mod (p-1)} (mod p));所以只需计算 (n^2 mod (p-1));这个东西远远超过 long long,要计算它的取模,可以使用这个小技巧:

    inline ll ksc(ll x, ll y, ll p){
    	ll z = (ld)x / p * y;
    	ll res=(ull)x * y - (ull)z *p ;
    	return (res + p) % p;
    }
    
    

    标程:

    cout << (2 * 1ll * qpow(2, ksc(n / 2, n / 2, mod - 1)) +
     qpow(2, ksc(n / 2, n, mod - 1)) + qpow(2, ksc(n, n, mod - 1))) 
    % mod * 1ll * inv4 % mod << endl;
    

    F. 天气之子

    考点: 计数问题,树论,树论是 noip / CSP 的几乎最重要的考点。

    题解: 这种方法叫做 贡献 法,考虑一个连通块在那些 ([l,r]) 中出现过;那么我们需要取其中一个点作为这个连通块的代表,那么我就取深度最浅的那个点作为连通块的代表结点。于是我们枚举每个结点作为连通块的最浅结点,显然它能作为最浅结点当且仅当它的父节点没有被取到,当它的父节点被取到时,它就不是最浅借点,也可以认为这个连通块它不存在。于是我们快乐地得到如下代码:

    标程:

    u64 ans = 0;
    for (int i = 2; i <= n; i++)
    {
    	if (fat[i] < i)
    	{
    		ans += (i - fat[i]) * 1ll * (n - i + 1);
    	}
    	else
    	{
    		ans += (fat[i] - i) * 1ll * i ;
    	}
    }
    
    
    as 0.4123
  • 相关阅读:
    Scrapy settings 并发数更改
    tp5 规避 [ error ] 未定义数组索引
    967. Numbers With Same Consecutive Differences
    846. Hand of Straights
    1103. Distribute Candies to People
    559. Maximum Depth of N-ary Tree
    1038. Binary Search Tree to Greater Sum Tree
    538. Convert BST to Greater Tree
    541. Reverse String II
    1551. Minimum Operations to Make Array Equal
  • 原文地址:https://www.cnblogs.com/Linshey/p/14109411.html
Copyright © 2020-2023  润新知