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] x[l,r]之间满足 ( x   m o d   a )   m o d   b ≠ ( x   m o d   b )   m o d   a (x\bmod a)\bmod b\neq (x\bmod b)\bmod a (xmoda)modb=(xmodb)moda

可以知道可以求出0~r之间满足的数 与 0~l-1之间的数做差得出答案
推了很久,最后打表给出0~max(a,b)-1的数不满足,max(a,b)~LCM(a,b)的数满足。
看了别人的推导,满足的数为 x = k × l c m + x   m o d   a   m o d   b x=k\times lcm+x\bmod a\bmod b x=k×lcm+xmodamodb,即暴力求出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个物品,每个物品大小为 a i a_i ai,大小范围为k,给出每个背包的现在 c i c_i ci表示大小超过i的数必须 ≤ c i \leq c_i ci

因为给出 c i c_i ci满足单调递减,可以从大到小 k → 1 k\rightarrow1 k1贪心选元素,每个背包能放就放

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 ( n n − k ) { n n − k } 2{n\choose n-k}\left\{\begin{matrix}n\\n-k\end{matrix}\right\} 2(nkn){nnk}
代入第二类斯特灵公式求解

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);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值