zoukankan      html  css  js  c++  java
  • Codeforces Round #548 Div2 A~C题解

    闲话

    这场的D题也是个神仙题,标程用的是反演套DP.由于我不会写期望,先放着等以后点了数学科技再来.然后对于这场排名来说也就是拼ABC手速了,由于VP的时候CF炸了导致我一直没提交代码就很谔谔.C题虽然比较水,但是因为一开始走错方向了导致一直没写出来,不过比以前的情况要好一点的就是现在有时候也能把ABC打出来了,虽然时间和罚时上仍然很垃圾,不过在看到一个不会的问题,逐步思考解决的方向这件事上有了一点小小的进步.

    A. Even Substrings

    原题大意:给定了一个字符串s,现在要求这段字符串里连续的子段表示的数是偶数的个数,注意只要是位置不同就算不同.
    数据范围:
    (1 leq |s| leq 65000)

    思路

    显然对于一个表示出来是偶数的数,末尾一定是偶数,则对于字符串里的每一个偶数考虑以他为结尾的偶数有多少个,最后累加起来就得到了答案,比较简单.

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int main()
    {
    	ios::sync_with_stdio(0);cin.tie(0);
    	int n;cin >> n;
    	string s;cin >> s;
    	ll res = 0;
    	for(int i = 0;i < n;++i)	
    		if((s[i] - '0') % 2 == 0)
        		res += i +1;
        cout << res;
        return 0;
    }
    

    B. Chocolates

    原题大意:商店里面有(n)种巧克力,对于(i)种巧克力有(a_i)个.假设手上的钱是无限的,如果购买的(i)种巧克力的数量是(x_i)的话,则整个(x)序列需要满足他是一个严格上升的序列或者前面都是(0).问在此限制下,最多能买多少个巧克力.
    注意:0也要算进去.
    数据范围:
    (1 leq n leq 2 *10^5)

    思路

    显然由于题目的限制及其的强,顺理成章的就可以从最后一位开始往前推,因为最后一位如果是(0)的话则前面必须全部是(0).于是这个题的思路也就比较好想了,从最后一位开始贪心,当前这一位是之前选的和本位最多能买的数量取一个较小值,一直往前直到不能买位置.

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N = 2e5+7;
    int a[N];
    ll res = 0,x = 1e9+7;
    int main()
    {
    	int n;scanf("%d",&n);
    	for(int i = 1;i <= n;++i)	scanf("%d",&a[i]);
        for(int i = n;i >= 1;--i)
        {
        	x = min(x - 1,1ll*a[i]);
        	if(x >= 0)	res += x;
        }
        printf("%lld",res);
        return 0;
    }
    

    C. Edgy Trees

    原题大意:给定一个树,树上的每条边要么是黑色的要么是红色的.这样定义一个牛逼的(k)路径:首先整个路径里面包含(k)个点,这些点可以有重复,其次这样描述这条路径:顺次的从第一个元素按最短路径走到第二个元素,第二个元素再按最短路径走到第三个元素,直到结束.如果这些路径上经过了一个黑色的边,则认为这个(k)路径是牛逼的.现给定(k),求这个树上牛逼的(k)路径有多少个.答案对(10^9+7)取模.
    数据范围:
    (2 leq n leq 10^5)
    (2 leq k leq 100)

    思路

    先想能不能正面突破,如果要正面突破的话,一个比较直观的想法就是看怎么直接构造出这个(k)路径,对于第一个点显然是(n)种选择,第二个点就是第一个点出发有多少个经过黑色边的路径.好到这里就有两个问题了:首先第一个点走到第二个点不一定非要经过黑边,可能是后面的,第二你根本不能从这个信息里知道第三位应该填什么.正面突破是及其困难的,考虑有没有反向的思路.
    由于这个题要求的是至少,那反过来就是一个都没有,也就是说答案是全集挖掉只有白色边连接的路径,全集比较简单,就是(n^k).考虑怎么求出树上只有白色边连接的路径,显然可以类似缩点的方式,把树上只有白色边相连的点看成是一个点,缩完之后的树上只有黑边,那么显然如果跨点选择必然导致走过一个黑边,因此答案就是这些划分完之后的集合里自己可以组合出多少个(k)路径.假设一个缩完的集合里有(a)个数,那么要搞出一个(k)路径也就是在这个集合里面有重复的选择出(k)个元素,显然有(k)部,每一步有(a)个选择,因此对这个集合来说,他能构造出来的(k)路径就有(a^k)条,不同的集合之间不能相连,因此加法原理适用,最后所有的加起来再被全集一减,答案就出来了.
    特别注意由于是一个减法的形式,一定要注意对负数取模,虽然这个题应该是不会出错的,但是一定要注意这点.负数取模的问题往往比较隐藏.只有平常多加细心考虑.

    思路

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+7,M = 2 * N,MOD = 1e9+7;
    int edge[M],succ[M],color[M],ver[N],idx;
    int id[N];
    ll cnt[N];
    void dfs(int u)
    {
    	for(int i = ver[u];~i;i = succ[i])
    	{
    		int v = edge[i];
    		if(id[v] || color[i] == 1)	continue;
    		id[v] = id[u];
    		dfs(v);
    	}
    }
    void add(int u,int v,int col)
    {
    	edge[idx] = v;
    	color[idx] = col;
    	succ[idx] = ver[u];
    	ver[u] = idx++;
    }
    ll qmul(ll a, ll b, ll P) 
    {
      	ll L = a * (b >> 25LL) % P * (1LL << 25) % P;
      	ll R = a * (b & ((1LL << 25) - 1)) % P;
      	return (L + R) % P;
    }
    ll qpow(ll a,ll b,ll p)
    {
    	ll res = 1 % p;
    	while(b)
    	{
    		if(b & 1)	res = qmul(res,a,p);
    		a = qmul(a,a,p);
    		b >>= 1;
    	}
    	return res;
    }
    int main()
    {
    	memset(ver,-1,sizeof ver);
    	int n,k;scanf("%d%d",&n,&k);
    	for(int i = 1;i < n;++i)
    	{
    		int u,v,c;scanf("%d%d%d",&u,&v,&c);
    		add(u,v,c);add(v,u,c);
    	}
    	int totid = 0;
    	for(int i = 1;i <= n;++i)
    		if(!id[i])
    		{
    			id[i] = ++totid;
    			dfs(i);
    		}
    	for(int i = 1;i <= n;++i)
    		++cnt[id[i]];
    	ll res = 0;
    	for(int i = 1;i <= totid;++i)
    		res = (res + qpow(cnt[i],k,MOD)) % MOD;
    	res = ((qpow(n,k,MOD) - res) % MOD + MOD) % MOD;
        printf("%lld",res);
        return 0;
    }
    
  • 相关阅读:
    POJ 1988 Cube Stacking(带权并查集)
    POJ 1414 Life Line(搜索)
    POJ 3468 A Simple Problem with Integers (线段树多点更新模板)
    二叉树前序遍历+中序遍历->后序遍历
    POJ 1061 青蛙的约会(扩展欧几里得)
    XDOJ 1020 ACMer去刷题吧(基础dp)
    POJ 2823 Sliding Window (线段树区间查询)
    线段树学习(一)
    UVA 294 Divisors( 因子分解)
    YYN图论学习路线(推荐)
  • 原文地址:https://www.cnblogs.com/HotPants/p/13475565.html
Copyright © 2011-2022 走看看