首页 > 其他分享 >Codeforces Round 952 (Div. 4)

Codeforces Round 952 (Div. 4)

时间:2024-06-13 19:23:43浏览次数:26  
标签:geq frac int 952 Codeforces cdot Div include displaystyle

A

读入两个字符串,交换第一位即可。

B

题意

给定整数 \(n\),求一个整数 \(x\),满足:

  • \(2\leq x \leq n\)。

  • \(\displaystyle \sum\limits_{i = 1}^k i\cdot x\) 最大,其中 \(k\) 为满足 \(kx \leq n\) 最大的正整数。

思路

赛时思路

可以直接枚举 \(x\) 的所有情况,暴力计算答案。

由于是像筛法那样的暴跳,总复杂度为 \(O(Tn\log n)\)。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;

const int N = 1e6 + 100; 
int t , n;

signed main() {
	cin >> t;
	while(t --) {
		cin >> n;
		int maxx = 0 , ans = n;
		for(int j = 2;j <= n;j ++) {
			int sum = 0;
			for(int k = 1;k * j <= n;k ++) 
				sum += k * j;
			if(sum > maxx) {
				ans = j;
				maxx = sum;
			}
		}
		cout << ans << "\n";
	}
	return 0;
}

另解

我们注意到当 \(n = 3\) 时,答案为 \(3\)。否则答案一定为 \(2\)。

证明:

\(n=2\) 和 \(n = 3\) 的情况显然,这里我们证明 \(n \geq 4\) 的情况。

根据等差数列求和公式我们得到:

\[\displaystyle \sum\limits_{i = 1}^k i\cdot x = \displaystyle x\cdot \frac{(1+\lfloor \frac{n}{x} \rfloor)\cdot \lfloor \frac{n}{x} \rfloor}{2} \]

\[\because \displaystyle x\cdot\left\lfloor \frac{n}{x}\right\rfloor = n - n \bmod x \]

\[\therefore \displaystyle n - x + 1\leq x\cdot\left\lfloor \frac{n}{x}\right\rfloor \leq n \]

根据以上式子放缩:

当 \(x\) 取 \(2\),原式 \(\leq \displaystyle \frac{(n - 1)\cdot(1+\lfloor \frac{n}{2} \rfloor)}{2}\)。

当 \(x\) 取 \(s(s \geq 3)\),原式 \(\geq \displaystyle \frac{n\cdot(1+\lfloor \frac{n}{s} \rfloor)}{2} \geq \displaystyle \frac{n\cdot(1+\lfloor \frac{n}{3} \rfloor)}{2}\)。

上式比下式:

\[\displaystyle \frac{n - 1}{n} \cdot \frac{1+\lfloor \frac{n}{2} \rfloor}{1+\lfloor \frac{n}{3} \rfloor} \]

我们只需要证明这个式子 \(\geq 1\) 即可证明 \(2\) 为答案,这里我们分类讨论一下。

若 \(n = 6m\) 或 \(6m + 1\),此时 \(m \geq 1\),则原式 \(\displaystyle\geq \frac{n - 1}{n}\cdot \frac{1+3m}{1+2m} \geq \frac{5}{6}\cdot\frac{4}{3} = \frac{10}{9}\)。

若 \(n = 6m + 2\),此时 \(m \geq 1\),则原式 \(\displaystyle\geq \frac{n - 1}{n}\cdot \frac{2+3m}{1+2m} \geq \frac{7}{8}\cdot\frac{5}{3} = \frac{35}{24}\)。

若 \(n = 6m + 3\),此时 \(m \geq 1\),则原式 \(\displaystyle\geq \frac{n - 1}{n}\cdot \frac{2+3m}{2+2m} \geq \frac{8}{9}\cdot\frac{5}{4} = \frac{10}{9}\)。

若 \(n = 6m + 4\) 或 \(6m + 5\),此时 \(m \geq 0\),则原式 \(\displaystyle\geq \frac{n - 1}{n}\cdot \frac{3+3m}{2+2m} \geq \frac{3}{4}\cdot\frac{3}{2} = \frac{9}{8}\)。

证毕。

如果有简单证明请速速告诉我,我被这证明折磨麻了!

C

题意

一个序列中若存在一个数等于序列中其他所有数的和,则该序列为好序列。

问有多少个 \(k(1\leq k \leq n)\),满足 \((a_1,a_2,\cdots,a_k)\) 是好序列。

思路

如果存在一个数等于其他数的和,那么这个数必然是序列中最大的。

设最大的数为 \(s_0\),序列和为 \(sum\),则对于每个 \(k\) 只需判断是否满足 \(s_0 = sum - s_0\) 即可。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;

const int N = 1e6 + 100; 
int t , n , a[N];

signed main() {
	cin >> t;
	while(t --) {
		cin >> n;
		int maxx = 0 , sum = 0 , ans = 0;
		for(int i = 1;i <= n;i ++) {
			cin >> a[i];
			sum += a[i];
			maxx = max(maxx , a[i]);
			if(maxx * 2 == sum) ans ++;
		}
		cout << ans << "\n";
	}
	return 0;
}

D

题意

给定一个由 #. 组成的 \(n \times m\) 的网格,网格上存在一个由 # 构成的完整的曼哈顿圆,求这个曼哈顿圆的中心。

以 \((a,b)\) 为中心,半径为 \(r\) 的曼哈顿圆的定义:将与 \((a,b)\) 曼哈顿距离小于 \(r\) 的点全设置成 #,\(r\) 为正整数。

思路

画图发现曼哈顿圆一定是一个菱形(\(r = 1\) 的时候是一个点)。

那么中心点就是 # 最长的一行的连续 # 的中点。

扫一遍得到横坐标 \(x_0\),记录下该行第一个 # 纵坐标 \(y_1\) 和最后一个 # 纵坐标 \(y_2\),中心即为 \(\displaystyle (x_0 , \frac{y_1+y_2}{2})\)。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;

const int N = 1e6 + 100;
char ch[N];
int t , n , m , a[N];

signed main() {
	cin >> t;
	while(t --) {
		cin >> n >> m;
		int maxx = 0;
		int x , y;
		for(int i = 1;i <= n;i ++) {
			scanf("%s" , ch + 1);
			int now = 0 , zh = 0 , zq = 0;
			for(int j = 1;j <= m;j ++) {
				if(ch[j] == '#') {
					if(now == 0) zq = j;
					now ++ , zh = j;
				}
			}
			if(now > maxx) {
				maxx = now;
				x = i;
				y = (zq + zh) / 2;
			}
		}
		cout << x << ' ' << y << "\n";
	}
	return 0;
}

E

思路

可以枚举长和宽 \(x_0\) 和 \(y_0\),这样就直接能算出高为 \(\displaystyle \frac{k}{x_0y_0}\) 了,但前提是 \(k\) 能被 \(x_0y_0\) 整除。

根据乘法原理可得,放置方案数为 \(\displaystyle(x - x_0 + 1)(y - y_0 + 1)(z-\frac{k}{x_0y_0} + 1)\),取个 \(\max\) 即可。

复杂度 \(O(xy)\)。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;

const int N = 1e6 + 100;
char ch[N];
int t , x , y , z , k;

signed main() {
	cin >> t;
	while(t --) {
		cin >> x >> y >> z >> k;
		int maxx = 0;
		for(int i = 1;i <= x;i ++) {
			for(int j = 1;j <= y;j ++) {
				if(k % i == 0) {
					int now = k / i;
					if(now % j == 0) {
						int dsw = now / j;
						maxx = max(maxx , (x - i + 1) * (y - j + 1) * max(0ll , (z - dsw + 1)));
					}
				}
			}
		}
		cout << maxx << "\n";
	}
	return 0;
}

F

小时候看这集 fst 了。

题意

有个 boss 有 \(h\) 的血量,你作为玩家有 \(n\) 个技能,每个技能伤害为 \(a_i\),冷却时间为 \(c_i\)。

每一回合你可以使用所有已冷却的技能,然后该技能会进入冷却并在 \(c_i\) 回合后才可使用。

求最少多少回合击败 boss。

思路

对 boss 造成的伤害是随着回合数单调不降的。

所以直接二分答案就行了。

若进行了 \(x\) 回合,则技能 \(i\) 的使用次数为 \(\displaystyle\frac{x - 1}{c_i} + 1\),造成的伤害为 \(\displaystyle a_i\cdot(\frac{x - 1}{c_i} + 1)\)。

注意:计算总伤害会爆 long long。所以在计算过程中若足够击败 boss 就应直接退出循环。笔者就是因为这个 fst 了。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;

const int N = 1e6 + 100;
char ch[N];
int t , n , m , z , k , a[N] , b[N];

signed main() {
	cin >> t;
	while(t --) {
		cin >> n >> m;
		for(int i = 1;i <= m;i ++) 
			cin >> a[i];
		for(int i = 1;i <= m;i ++) 
			cin >> b[i];
		int l = 1 , r = 1e12;
		int ans = 1;
		while(l <= r) {
			int mid = l + r >> 1;
			int sum = 0;
			for(int i = 1;i <= m;i ++) {
				int cs = (mid - 1) / b[i] + 1;
				sum += cs * a[i];
				if(sum >= n) break;
			}
			if(sum >= n) {
				ans = mid;
				r = mid - 1;
			} else l = mid + 1;
		}
		cout << ans << "\n";
	}
	return 0;
}

G

题意

设 \(D(x)\) 为 \(x\) 的各数位之和。

给定 \(l,r,k\),求多少 \(n\) 满足:

  • \(10^l \leq n < 10^r\)。

  • \(k\cdot D(n) = D(k\cdot n)\)。

思路

首先满足该条件的一个充分条件是 \(n \times k\) 不产生进位。

所以我们猜测这个也是它的必要条件,考虑证明。

对于单独的一位 \(n_i\),若它乘 \(k\) 有进位。

则 \(k \cdot D(n_i) = kn_i\),\(\displaystyle D(k\cdot n_i) = \frac{kn_i}{10} + (kn_i \bmod 10)\)。

后者小于前者,证明:

把 \(kn_i\) 表示成 \(10x + y\),\(x\) 为正整数,\(y\) 为非负整数,且 \(y < 10\)。则 \(D(k\cdot n_i)\) 为 \(x + y\)。证毕。

所以必要条件成立。

计算答案

这题计算答案也没那么简单,根据最高位不能填 \(0\),所以最高位有 \(\displaystyle \frac{9}{k}\) 种填法,其他位有 \((\displaystyle \frac{9}{k} + 1)\) 种填法。

对于 \(10^i \le n < 10^{i+1}\),满足条件的情况共 \(\displaystyle \frac{9}{k}\cdot (\frac{9}{k} + 1)^i\) 种。

所以对于 \(10^l \le n < 10^{r}\),满足条件的情况共 \(\displaystyle \frac{9}{k}\cdot \sum\limits_{i = l}^{r - 1}(\frac{9}{k} + 1)^i\) 种。

根据等比数列求和公式可得到上式等于 \(\displaystyle (\frac{9}{k}+1)^l\cdot ((\frac{9}{k}+1)^{r-l} - 1)\)。

这个式子用快速幂和逆元相关知识就能求出来了。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;

const int N = 1e6 + 100;
const int mod = 1e9 + 7;
char ch[N];
int t , n , m , z , k , a[N] , b[N];

int ksm(int x,int y) {
	int res = 1;
	for(;y;y >>= 1 , x = x * x % mod) 
		if(y & 1) 
			res = res * x % mod;
	return res;
}

signed main() {
	cin >> t;
	while(t --) {
		cin >> n >> m >> k;
		int wd = (9 / k);
		int now = (((ksm(wd + 1 , m - n) - 1) % mod) + mod) % mod; 
		now = ksm(wd + 1 , n) % mod * now % mod;
		cout << now << "\n"; 
	}
	return 0;
}

H1

题意

给定一个由 #. 组成的 \(n \times m\) 的网格,请进行以下的操作一次,使图中由 # 构成的连通块最大。

操作:选定一行一列,将其全部变为 #

输出操作后最大连通块点数。

思路

很自然地想到枚举每一行/每一列,难点在于怎么计算答案。

我们先考虑填行的情况。

如果我们把一行填满,则相当于桥一样把这条线两边的连通块连起来了。

所以当我们枚举第 \(i\) 行时,答案为:第 \(i\) 行 . 的数量,并将第 \(i - 1\) 到 \(i + 1\) 这三行的连通块不重不漏地加入贡献。

这里选择先 \(\text{dfs}\) 给每个连通块标个号,并计算该连通块大小。时间复杂度 \(O(nm)\)。

然后计算答案的时候,用 \(\text{map}\) 对编号去一下重,就能做到不重了。

填列的做法和填行没有任何区别。

代码

代码复杂程度远难于思路的一题。

Link.

H2

题意

给定一个由 #. 组成的 \(n \times m\) 的网格,请进行以下的操作一次,使图中由 # 构成的连通块最大。

操作:选定一行一列,将其全部变为 #

输出操作后最大连通块点数。

思路

如果使用 Easy Version 的思路,复杂度是 \(O(n^2m^2)\) 的,无法接受。

由于选一行一列会有交集的连通块,所以无法单独考虑行或列再计算答案。

因此还是考虑枚举行和列,到这复杂度为 \(O(nm)\)。

既然暴力计算答案不行,那么我们就想想能不能预处理出答案。

对于一个连通块,向上延伸到 \(l_1\) 行,向下延伸到 \(r_1\) 行,向左延伸到 \(l_2\) 列,向右延伸到 \(r_2\) 列,那么它将对 \(l_1 - 1\) 到 \(r_1 + 1\) 行和 \(l_2 - 1\) 到 \(r_2 + 1\) 列有贡献。

这个贡献,我们用差分数组记录,比如行差分数组 \(s_1\) 和连通块大小 \(c\),我们将 \(s_1\) 的 \(l_1 - 1\) 的位置 \(+c\),\(r_1 + 2\) 的位置 \(-c\),在差分数组构造完之后前缀和一下就行了。

列差分数组也是同理。

做到这里会发现枚举行列的话,会有连通块被重复计算了一次。那么考虑怎么减掉这个贡献。

再整一个二维数组 \(S_{i,j}\),代表第 \(i\) 行和第 \(j\) 列重复计算的连通块贡献的差分数组。一个连通块有重复贡献的部分为左上角为 \((l_1 - 1,l_2 - 1)\),右下角为 \((r_1 + 1,r_2 + 1)\) 的矩形,把这个矩形二维差分的形式存在 \(S\) 里,然后再转回来即可。

时间复杂度 \(O(nm)\)。

代码

Link.

标签:geq,frac,int,952,Codeforces,cdot,Div,include,displaystyle
From: https://www.cnblogs.com/NEUQ-zyb/p/18246606

相关文章

  • Codeforces Round 952 (Div. 4)
    link赛时过了ABCD,rank15270,我嘞个豆啊,虽然菜成shi了,但是打得很开心,凌晨一点多还兴奋得不得了。就是网络好差,比赛开始好几分钟了还被关在外边。A-CreatingWordsB-MaximumMultipleSum签到题,略C-GoodPrefixes想到用前缀和,一开始写成每次往后一位后缀,只对最后一......
  • 如何对嵌套 div 表格进行排序?
    我正在寻找一种解决方案,以便能够根据一个"列"中的值对div表格进行排序。在下面的示例中,排序列的div类为"text-fl"。交互式排序,在这种排序中,数据最初是按照代码中的方式加载的,但如果用户选择按值排序,他们可以点击列标题。由于我的数据不在列表中,因此我认为我无......
  • Codeforces Round 952 (Div. 4)
    A.CreatingWordsvoidsolve(){ stringa,b; cin>>a>>b; swap(a[0],b[0]); cout<<a<<''<<b<<'\n';}B.MaximumMultipleSum总结:作为一个等差数列,快速的找到最高次系数,以及快速求和..C=n/x,sum=(c*x+......
  • 【结构识别】Reconstructing propagation networks with natural diversity and ident
    摘要从数据中重构复杂网络结构和动力学的能力是理解和控制复杂系统集体动力学的基础。尽管最近在这方面取得了进展,但利用随机动态过程的有限时间序列重建网络仍然是一个尚未解决的问题。我们提出了一个基于压缩感知的框架去重构发生随机扩散动力学的复杂网络。我们将该方法应用于......
  • Codeforces Problem 1980B Choosing cubes(基本排序)
    timelimitpertest1secondmemorylimitpertest256megabytesinputstandardinputoutputstandardoutputDmitryhas n......
  • LeetCode 974 Subarray Sums Divisible by K All In One
    LeetCode974SubarraySumsDivisiblebyKAllInOneLeetCode974能被K整除的子数组之和errosfunctionsubarraysDivByK(nums:number[],k:number):number{//-5/0/5letcount:number=0;//单个元素for(leti=0;i<nums.length;i++){......
  • 动物静态HTML网页作业作品 大学生野生动物保护网页设计制作成品 简单DIV CSS布局网站
    ......
  • 如何提升自己的Codeforces分数
    如何提升自己的Codeforces分数此篇为XiaoMo247对原文的总结,原文是MasatakaYoneda/E869120的AWaytoPracticeCompetitiveProgramming(FromRating1000to2400+)目前只读了1000-1400和1400-1900,等作者codeforces分数到了1900再更新后面的。首先是作者对三......
  • Codeforces Round 837题解(A、B)
    A.HossamandCombinatorics\(|a_i-a_j|\)最大的就是最大值和最小值,注意要开longlong。intn;inta[N];voidsolve(){cin>>n;intmin_v=INF,max_v=0;for(inti=1;i<=n;i++){cin>>a[i];min_v=min(min_v,a[i......
  • Codeforces 800-1300 刷题笔记
    CF1946BMaximumSum这道题是一道贪心题。对于第\(1\)次操作,选择的话肯定是选最大的好,所以我们会找出原序列的最大子段和进行插入,为了使下一次的插入子段更大,所以我们一定会插入原序列的最大子段和中。进行\(m\)次操作,执行\(m\)次上述操作即可。直接模拟的话肯定不行,我们......