Codeforces Round #548 (Div2)

Codeforces Round 548(Div. 2)


题目地址

A. Even Substrings

题目大意:

大概就是让你找到所有的偶数,然后让你累加这个偶数及之前的所有数的个数
#include
using namespace std;
const int MAXN = 65009;

int n, ans;
char s[MAXN];

int main()
{
	cin >> n >> s + 1;
	for (int i = 1; i <= n; i++) {
		int x = s[i] - '0';
		if (x % 2 == 0)ans += i;
	}
	cout << ans << endl;
	return 0;
}

B. Chocolates

题目大意:

给你一个长度为n的序列,在每一位去取数字,每次取得的数要小于等于数列中的当前数,可以不取,最后取得的数列要求严格递增

问能够取得的数列的和最大是多少

思路:

我们可以知道,最后取得的数一定是最大的数,所以我们倒着来取,如果要取的当前数小于已经取得最后一位数,我们就取当前数

若不小于,我们就取已经取得的最后一位数减一,这样可以满足取得的最大

#include
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 10;

int main()
{
	ios::sync_with_stdio(false); cin.tie();
	int n, a[MAXN] = {0}, last = 0;
	ll ans = 0;
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> a[i];
	for (int i = n; i >= 1; i--) {
		if (i == n || a[i] < last) {
			ans += a[i];
			last = a[i];
		} else {
			ans += max(0, last - 1);
			last = max(0, last - 1);
		}
	}
	cout << ans << endl;
	return 0;
}

C. Edgy Trees

题目大意:

给你由n个顶点构成的一棵树,树的边分为红黑两种,由1和0代表,求经过k个顶点且至少有一条黑色的边的集合的个数,顶点可以重复取

思路:

直接求要求的集合的个数很难,我们可以先求出总数,为N^K个,然后减去经过k个顶点且不经过黑色的边的集合个数,是每个红色联通块

内的集合数之和,所以要求一下红色的联通块num,然后累加num^k即可

#include
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int MAXN = 1e5 + 10;

ll ans, cnt;
int n, k, tot;
bool vis[MAXN];
vectorq[MAXN];

ll ksm(ll a, ll b)//快速幂
{
	ll res = 1;
	while (b) {
		if (b & 1)res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}

void dfs(int u)//dfs求联通块
{
	cnt++;
	vis[u] = 1;
	for (auto v : q[u])if (!vis[v]) {
			dfs(v);
		}
}

int main()
{
	cin >> n >> k;
	for (int i = 1; i < n; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		if (w == 0) {
			q[u].push_back(v);
			q[v].push_back(u);
		}
	}
	ll ans = ksm(n, k);
	for (int i = 1; i <= n; i++) {
		if (!vis[i]) {
			cnt = 0;
			dfs(i);
			ans = (ans - ksm(cnt, k) + mod) % mod;
		}
	}
	cout << ans << endl;
	return 0;
}

你可能感兴趣的:(ACM)