• Codeforces Round #447 (Div. 2) 题解


    Problem A

    直接暴力,当然我O(n)过的。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    
    
    int ans = 0;
    char s[205];
    int a[205], b[205];
    int n;
    
    
    int main(){
    
    
    	scanf("%s", s + 1);
    	n = strlen(s + 1);
    
    	rep(i, 1, n) if (s[i] == 'Q') a[i] = a[i - 1] + 1;
    	else a[i] = a[i - 1];
    
    	dec(i, n, 1) if (s[i] == 'Q') b[i] = b[i + 1] + 1;
    	else b[i] = b[i + 1];
    
    	rep(i, 1, n) if (s[i] == 'A') ans += a[i] * b[i];
    
    	printf("%d
    ", ans);
    
    
    	return 0;
    }
    

      

    Problem B

    打表找规律……当k为-1且n和m奇偶性不同的时候答案为0。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    
    const LL mod = 1e9 + 7;
    
    LL n, m;
    int k;
    
    inline LL Pow(LL a, LL b, LL Mod){
            LL ret(1);
            for (; b; b >>= 1, (a *= a) %= Mod) if (b & 1) (ret *= a) %= Mod;
            return ret;
    }	
    
    
    int main(){
    
    	scanf("%lld%lld%d", &n, &m, &k);
    	if (k == 1){
    		LL yy = n - 1;
    		LL hh = Pow(2, yy, mod);
    		LL ans = Pow(hh, m - 1, mod);
    		printf("%lld
    ", ans);
    	}
    
    	else{
    		LL tt = n + m;
    		if (tt % 2 == 1) return 0 * puts("0");
    		if (n % 2 == 1){
    			LL oo = (n + 1) / 2;
    			LL pp = oo - 1;
    			LL mul = Pow(16, pp, mod);
    			LL mm = m / 2;
    			LL ans = Pow(mul, mm, mod);
    			printf("%lld
    ", ans);
    		}
    
    		else{
    			LL xx = n / 2, yy = m / 2;
    			LL mul = 4 * Pow(16, xx - 1, mod) % mod;
    			LL ff = 2 * Pow(4, xx - 1, mod) % mod;
    			LL ans = ff * Pow(mul, yy - 1, mod) % mod;
    			printf("%lld
    ", ans);
    		}
    
    	}		
    
    
    	return 0;
    }
    

      

    Problem C

    构造题(赛时被X……)

    若最大的那个不能整除所有比他小的数,那么无解

    否则就按照s1,s1,s2,s1,s3,s1,s4,s1,...sn,s1这么输出。

    关键是想到。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, f)	for (int i(a); i <= (f); ++i)
    #define dec(i, a, f)	for (int i(a); i >= (f); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    const int N = 1e6;
    
    
    int n;
    int c[10100];
    int f[N];
    
    int main(){
    
    	scanf("%d", &n);
    	rep(i, 1, n) scanf("%d", c + i);
    	rep(i, 2, n) if (c[i] % c[1]) return 0 * puts("-1");
    	printf("%d
    ", n << 1);
    	rep(i, 1, n) printf("%d %d
    ", c[1], c[i]);
    	putchar(10);
    }
    

      

    Problem D

    暴力存下所有点的所有儿子到他的距离。

    因为这是完全二叉树所以内存可以承受。

    空间开销$nlogn$,时间复杂度$O(nlog^{2}n)$,如果用归并排序的话那就$O(nlogn)$

    然后查询的时候一步步往上爬,把符合条件的答案统计进来。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    typedef long long LL;
    typedef pair <int, LL> PII;
    
    const int N = 1e6 + 10;
    
    int n, m;
    vector <LL > g[N], s[N];
    LL l[N], ans = 0;
    
    inline int fa(int x){ return x >> 1;}
    inline int ls(int x){ return x << 1;}
    inline int rs(int x){ return x << 1 | 1;}
    
    PII calc(int x, LL len){
    	if (len < 0) return MP(0, 0);
    	if (x > n) return MP(0, 0);
    	int sz = (int)g[x].size();
    	if (g[x][sz - 1] <= len) return MP(sz, s[x][sz - 1]);
    
    	int l = 0, r = sz - 1;
    	while (l + 1 < r){
    		int mid = (l + r) >> 1;
    		if (g[x][mid] <= len) l = mid;
    		else r = mid - 1;
    	}
    
    	int t;
    	if (g[x][r] <= len) t = r; else t = l;
    	return MP(t + 1, s[x][t]);	
    
    }
    
    void dfs(int x){
    	if (ls(x) <= n){
    		dfs(ls(x));
    		for (auto u : g[ls(x)]) g[x].push_back(l[ls(x)] + u);
    	}
    
    	if (rs(x) <= n){
    		dfs(rs(x));
    		for (auto u : g[rs(x)]) g[x].push_back(l[rs(x)] + u);
    
    	}
    
    	g[x].push_back(0);
    	sort(g[x].begin(), g[x].end());
    }
    
    int main(){
    
    	scanf("%d%d", &n, &m);
    	rep(i, 2, n) scanf("%lld", l + i);
    
    	dfs(1);
    
    	rep(i, 1, n){
    		int sz = g[i].size();
    		s[i].resize(sz + 2);
    		s[0] = g[0];
    		rep(j, 1, sz - 1) s[i][j] = s[i][j - 1] + g[i][j];
    	}
    
    	while (m--){
    		int x, y;
    		LL len, Len;
    		scanf("%d%lld", &x, &len);
    		Len = len;
    		PII cnt = calc(x, len);
    		ans = 0;
    		ans = cnt.fi * len - cnt.se;
    		y = x, x = fa(x);
    		len -= l[y];
    		while (x && len >= 0){
    			if (ls(x) == y){
    				cnt = calc(rs(x), len - l[rs(x)]);
    				ans += cnt.fi * Len - cnt.se - cnt.fi * (Len - len + l[rs(x)]);
    			}
    
    			else{
    				cnt = calc(ls(x), len - l[ls(x)]);
    				ans += cnt.fi * Len - cnt.se - cnt.fi * (Len - len + l[ls(x)]);
    			}
    
    			ans += len;
    			y = x;
    			x = fa(x);
    			len -= l[y];
    		}
    		printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    

      

    Problem E

    预处理出所有强连通分量之后缩点。

    缩成的点的权值为该点代表的强连通分量的所有边的价值和(根据题目算出来)

    然后就变成了一个DAG,DP一下就可以了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    typedef long long LL;
    
    const int N = 1e6 + 10;
    
    vector <pair <int, int > > v[N], g[N];
    stack <int> stk;
    LL f[N], val[N];
    int n, m;
    int low[N], dfn[N], sccno[N];
    int num = 0, ti = 0;
    int s;
    
    void dfs(int x){
    	low[x] = dfn[x] = ++ti;
    	stk.push(x);
    	for (auto edge : v[x]){
    		int u = edge.fi, w = edge.se;
    		if (!low[u]){
    			dfs(u);
    			dfn[x] = min(dfn[x], dfn[u]);
    		}
    
    		else if (!sccno[u]) dfn[x] = min(dfn[x], low[u]);
    	}
    
    	if (dfn[x] == low[x]){
    		++num;
    		while (true){
    			int u = stk.top();
    			stk.pop();
    			sccno[u] = num;
    			if (u == x) break;
    		}
    	}
    }
    
    LL work(int x){
    	if (~f[x]) return f[x];
    	f[x] = 0;
    	for (auto edge : g[x]) f[x] = max(f[x], work(edge.fi) + edge.se);
    	return f[x] += val[x];
    }
    
    LL calc(int x){
    	int rt = sqrt(2 * x);
    	while ((LL)rt * (rt - 1) / 2 <= x) rt++;
    	while ((LL)rt * (rt - 1) / 2 >  x) rt--;
    	return (LL)rt * x - (LL)(rt + 1) * rt * (rt - 1) / 6;
    }
    
    int main(){
    
    	scanf("%d%d", &n, &m);
    	rep(i, 1, m){
    		int x, y, z;
    		scanf("%d%d%d", &x, &y, &z);
    		v[x].push_back(MP(y, z));
    	}
    
    	scanf("%d", &s);
    	dfs(s);
    
    	rep(i, 1, n){
    		for (auto edge : v[i]){
    			int x = i, y = edge.fi;
    			if (sccno[x] == sccno[y]) val[sccno[x]] += calc(edge.se);
    			else g[sccno[x]].push_back(MP(sccno[y], edge.se));
    		}
    	}
    
    	memset(f, -1, sizeof f);
    	printf("%lld
    ", work(sccno[s]));
    	return 0;
    }
    

      

  • 相关阅读:
    openSUSE字体美化
    [转摘]关于创建oracle dblink 过程的几点心得
    IList及泛型集合类转换DataTable
    C# 编码规范和编程好习惯
    随机数和随机字符串
    ThrowActivity 光阴的故事
    数据库的数据 转化为XML 在页面上浏览 光阴的故事
    EventHandlingScopeActivity 光阴的故事
    workflow 角色的使用关键 光阴的故事
    ConditionedActivityGroup 光阴的故事
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7895706.html
Copyright © 2020-2023  润新知