Educational Codeforces Round 107 (Rated for Div. 2)

比賽地址c++

A(水題)

題目連接
spa

題目:
有兩個計票員,\(n\)個觀衆,每一個觀衆能夠按順序投票,以下所示有三種票code

  • 1 表明支持
  • 2 表明不支持
  • 3 若是當前計票員收到的支持票數大於等於不支持票數,則投支持,反之不支持
    求出支持票數的最大值

解析:
讓一個計票員專門收反對票,另外一個計票員收其餘種類的票,很顯然答案就是\(1\)\(3\)的票數之和隊列

#include<bits/stdc++.h>
using namespace std;
/*===========================================*/
 
int main() {
	//FRE;
	int T, n, t;
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		int t1 = 0, t2 = 0;
		while (n--) {
			scanf("%d", &t);
			if (t & 1) ++t1;
			else ++t2;
		}
		printf("%d\n", t1);
	}
}

B(GCD)

題目連接
ci

題目:
給出\(a,b,c\)表明\(A,B,C\)三個數所表明的十進制位數,同時知足\(GCD(A,B)=C\),輸出知足條件的\(A,B\)字符串

解析:
因爲\(A=A'C,B=B'C\)\(A'\)\(B'\)互質,考慮C爲10的冪,能夠很好的控制A與B的位數,那麼任務就轉變成了尋找位數分別爲\(a-c+1\)\(b-c+1\)且互質的\(A'\)\(B'\),不難發現\(10^x與10^y+1\)必定互質(因爲前者只能質因數分解成若干個2與5的冪次,然後者必定不能被2或5整除),那麼問題迎刃而解get

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
/*===========================================*/

ll ten[10];

int main() {
	//FRE;
	int T;
	ten[1] = 1;
	for (int i = 2; i < 10; ++i)
		ten[i] = ten[i - 1] * 10;
	scanf("%d", &T);
	int a, b, c;
	while (T--) {
		scanf("%d%d%d", &a, &b, &c);
		printf("%lld %lld\n", ten[a - c + 1] * ten[c], (ten[b - c + 1] + 1) * ten[c]);
	}
}

C(思惟)

題目連接
⭐⭐數學

題目:
給出一疊牌,從上到下給出每一個牌的顏色,有\(m\)次詢問,每次詢問最上方顏色爲\(t\)的牌的位置,輸出,並把這張牌抽出放於牌頂string

解析:
因爲每次每次詢問最上方的牌,並把它放在牌頂,因此只須要記錄每種顏色最上方的牌,並在每次查詢時,維護好這個顏色隊列便可it

#include<bits/stdc++.h>
using namespace std;
/*===========================================*/

const int maxn = 3e5 + 5;

int q[maxn];
int cnt = 0;
bool vis[maxn];
int pos[maxn];

int main() {
	//FRE;
	int n, m, t;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &t);
		if (!vis[t]) {
			vis[t] = true;
			q[cnt++] = t;
			pos[t] = i;
		}
	}
	while (m--) {
		scanf("%d", &t);
		printf("%d ", pos[t]);
		int i = 0;
		for (; q[i] != t; ++i)
			++pos[q[i]];
		for (; i > 0; --i)
			q[i] = q[i - 1];
		pos[t] = 1;
		q[0] = t;
	}
}

D(構造)

題目連接
⭐⭐

題目:
若是\(s_i=s_j(i<j)\),且\(s_{i+1}=s_{j+1}\),則花費加1,如今給出字符串長度,以及字符集大小,求出最小代價的字符串

解析:
能夠嘗試考慮重複構造代價爲0的串,即時刻保證當前兩位後綴從未在以前出現過,能夠考慮這樣的構造方法,每次從\(a\)開始枚舉字符,先輸出一個\(cur\),再輸出\(cur\#\)\(cur\)表明當前字符,\(\#\)表明比\(cur\)大的字符,這樣能夠保證全部字符集合中全部兩兩組合都出現過

#include<bits/stdc++.h>
using namespace std;
/*===========================================*/

int n, m, c;

void P(int i) {
	printf("%c", i + 'a');
	if (++c == n) exit(0);
}

int main() {
	//FRE;
	scanf("%d%d", &n, &m);
	while (1) {
		for (int i = 0; i < m; ++i) {
			P(i);
			for (int j = i + 1; j < m; ++j)
				P(i), P(j);
		}
	}
}

E(dp+組合數學)

題目連接
⭐⭐⭐⭐

題目:
給出一個矩陣,\(o\)表明白塊,\(*\)表明黑塊,每一個白塊能夠染成redblue兩種顏色,橫排兩個連續的紅塊能夠防止一個多米諾牌,豎排兩個連續的藍塊能夠放置一個多米諾牌,多米諾牌不能重疊,每一個白塊必須被染色,問每種染色方案所能放置的最大多米諾牌數之和(取模\(998244353\)

解析:

  1. 考慮對於某一行連續的白塊,定義\(dp[i]\)爲前\(i\)個連續白塊最多能放置的多米諾牌之和,那麼對於\(dp[i+1]\)

    • 若是第\(i+1\)個白塊被染成藍色,則此時剩餘白塊的貢獻爲\(dp[i]\)
    • 若是第\(i+1\)個白塊被染成紅色
      • 若是第\(i\)個白塊被染成紅色,則此時剩餘\(i-1\)個白塊的貢獻爲\(dp[i-1]\),最後兩個紅塊對於總體的貢獻爲\(2^{i-1}\)
      • 若是第\(i\)個白塊被染成藍色,則此時剩餘白塊的貢獻爲\(dp[i-1]\)
  2. 綜上能夠獲得狀態轉移方程\(dp[i]=dp[i-1]+2*dp[i-2]+2^{i-2}\)

  3. 那麼統計全部連續的白塊行和白塊列,利用\(dp\)能夠\(O(1)\)求出這段白塊行/列對於每種染色矩陣的貢獻,所以假設這段白塊長度爲\(x\),答案加上\(dp[x]*2^{white-x}\)

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
/*===========================================*/
using namespace std;
const int maxn = 3e5 + 5, mod = 998244353.;
ll dp[maxn], two[maxn];
string e[maxn];

int main() {
	IOS
	two[0] = 1;
	int n, m;
	for (int i = 1; i < maxn; ++i)
		two[i] = two[i - 1] * 2 % mod;
	for (int i = 2; i < maxn; ++i)
		dp[i] = (dp[i - 1] + 2 * dp[i - 2] % mod + two[i - 2]) % mod;
	cin >> n >> m;
	int end = max(n, m);
	ll ret = 0, c;
	int white = 0;
	for (int i = 0; i < n; ++i) {
		cin >> e[i];
		for (auto& j : e[i])
			white += j == 'o';
	}
	for (int i = 0; i < n; ++i) {
		c = 0;
		for (int j = 0; j < m; ++j) {
			if (e[i][j] == 'o') ++c;
			else if (c) {
				ret = (ret + dp[c] * two[white - c]) % mod;
				c = 0;
			}
		}
		if (c)
			ret = (ret + dp[c] * two[white - c]) % mod;
	}
	for (int j = 0; j < m; ++j) {
		c = 0;
		for (int i = 0; i < n; ++i) {
			if (e[i][j] == 'o') ++c;
			else if (c) {
				ret = (ret + dp[c] * two[white - c]) % mod;
				c = 0;
			}
		}
		if (c)
			ret = (ret + dp[c] * two[white - c]) % mod;
	}
	cout << ret;
}
相關文章
相關標籤/搜索