Educational Codeforces Round 86

A

給出x,y兩個數,花費a元可以同時加1或減1,花費b元可以單個數加1或減1

貪心:將兩個數變到同樣大小,再一起減到0更優,注意特判2a和b的關係

int main()
{
	int t; scanf("%d", &t);
	while (t--) {
		ll x, y, a, b; scanf("%lld%lld%lld%lld", &x, &y, &a, &b);
		if (x < y) swap(x, y);
		if (b > 2 * a) b = 2 * a;
		printf("%lld\n", a * x + (b - a) * y);
	}
}

B

給出t串,求t爲s的子序列的滿足最小循環節的s串

可以得出,可以構造的s串的最小循環節只有1或者2,特判t串的循環節是否爲1

const int maxn = 1e2 + 5;
char s[maxn << 1], t[maxn];
int main()
{
	int T; scanf("%d", &T);
	while (T--) {
		scanf("%s", &t);
		int n = strlen(t);
		int cnt0 = 0, cnt1 = 0;
		for (int i = 0; i < n; ++i) {
			if (t[i] == '0') cnt0++;
			else cnt1++;
		}
		if (cnt0 == 0 || cnt1 == 0) {
			puts(t);
			continue;
		}
		int flg = 0;
		for (int i = 0; i < n; ++i) {
			if (t[i] == '0') {
				if (flg == 0) flg = 1;
				else if (flg == 1) {
					printf("01");
				}
			}
			else if (t[i] == '1') {
				if (flg == 0) {
					printf("01");
				}
				else if (flg == 1) {
					printf("01");
					flg = 0;
				}
			}
		}
		if (flg != 0) printf("01");
		printf("\n");
	}
}

C

給出a和b,求給出區間x[l,r]x\in [l,r]之間滿足(xmoda)modb(xmodb)moda(x\bmod a)\bmod b\neq (x\bmod b)\bmod a

可以知道可以求出0~r之間滿足的數 與 0~l-1之間的數做差得出答案
推了很久,最後打表給出0~max(a,b)-1的數不滿足,max(a,b)~LCM(a,b)的數滿足。
看了別人的推導,滿足的數爲x=k×lcm+xmodamodbx=k\times lcm+x\bmod a\bmod b,即暴力求出0~lcm之間的情況即可

ll a, b;
int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a % b);
}
int main()
{
	int t; scanf("%d", &t);
	while (t--) {
		int q; scanf("%lld%lld%d", &a, &b, &q);
		if (a > b) swap(a, b);
		int gap = a * b / gcd(a, b), incre = gap - b;
		while (q--) {
			ll l, r; scanf("%lld%lld", &l, &r); r++;
			ll rsum = r / gap * incre + (r % gap > b ? r % gap - b : 0);
			ll lsum = l / gap * incre + (l % gap > b ? l % gap - b : 0);
			printf("%lld ", rsum - lsum);
		}
		printf("\n");
	}
}

D

給出n個物品,每個物品大小爲aia_i,大小範圍爲k,給出每個揹包的現在cic_i表示大小超過i的數必須ci\leq c_i

因爲給出cic_i滿足單調遞減,可以從大到小k1k\rightarrow1貪心選元素,每個揹包能放就放

const int maxn = 2e5 + 5;
int cnt[maxn], c[maxn];
vector< vector<int> > res(1);
int main()
{
	int n, k; scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; ++i) {
		int x; scanf("%d", &x);
		cnt[x]++;
	}
	for (int i = 1; i <= k; ++i) scanf("%d", &c[i]);
	int pre = 0, ans = 0;
	for (int i = k; i; --i) {
		int now = 0;
		if (i != k && c[i] == c[i + 1]) now = pre;
		while (cnt[i]) {
			if (now == ans) {
				++ans;
				res.emplace_back();
				continue;
			}
			if (res[now].size() < c[i]) {
				res[now].emplace_back(i);
				--cnt[i];
			}
			else ++now;
		}
		pre = now;
	}
	printf("%d\n", ans);
	for (int i = 0; i < ans; ++i) {
		printf("%d", res[i].size());
		for (auto j : res[i]) printf(" %d", j);
		printf("\n");
	}
}

E

將“車”放在nxn的棋盤上,使每個格子都要被覆蓋(車可以覆蓋一排和一列的格子),且互相攻擊的車爲k個

要覆蓋所有格子,就每行或每列都存在車,畫圖可知,題意即求將n個元素放在n-k個集合中方案數。行列情況對稱,則答案爲
2(nnk){nnk} 2{n\choose n-k}\left\{\begin{matrix}n\\n-k\end{matrix}\right\}
代入第二類斯特靈公式求解

onst int maxn = 2e5 + 5;
const ll mod = 998244353;
ll fib[maxn];
ll qpow(ll a, ll b) {
	ll res = 1;
	while (b) {
		if (b & 1) res = 1ll * res * a % mod;
		b >>= 1;
		a = 1ll * a * a % mod;
	}
	return res;
}
ll c(int n, int m) {
	return 1ll * fib[n] * qpow(1ll * fib[m] * fib[n - m] % mod, mod - 2) % mod;
}
int main()
{
	fib[0] = 1;
	for (int i = 1; i < maxn; ++i) fib[i] = 1ll * fib[i - 1] * i % mod;
	ll n, k; scanf("%lld%lld", &n, &k);
	if (k == 0) printf("%lld\n", fib[n]);
	else if (k >= n) printf("0\n");
	else {
		int K = n - k;
		ll ans = 0;
		for (int i = 0; i <= K; ++i) {
			ans = (1ll * qpow(mod - 1, i) * c(K, i) % mod * qpow(K - i, n) % mod + ans) % mod;
		}
		ans = 2ll * c(n, K) * ans % mod;
		printf("%lld\n", ans);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章