CDZSC_2022寒假个人训练赛21级(4)题解

今天是大家喜欢()的数学场

  • 简单 A C D E
  • 中等 B F G
  • 困难 H

奇怪,我觉得挺难的H过了这么多,G这么简单居然没人过。
H 过这么多属实是震惊了。

A A Very Hard Question Gym - 101502A

题意

给你橙子数量y和价格涨幅x,问你原本买y个橙子的钱现在可以买几个。

题解

初中数学(注意浮点数和整数的变化,还有浮点数的误差)
看挺多人都掉这个坑里了,由于浮点数的精度问题,比如5,在计算机中可能会因为精度被表示成4.99999... ,如果你使用强制类型转换比如,(int)x,就会直接变成4,要尤其注意浮点数。

AC代码

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		int x,y;
		scanf("%d%d", &y, &x);
		printf("%.0f\n", y /( 1 + x * 0.01));
	}
}

B Building Numbers Gym - 101502F

题意

2 种操作

  • 1.将数字加一
  • 2.将数字乘二

给你一个数组,和 q 个查询,每一个查询,给你一个整数 l ,一个整数 r,问你, 将 1 分别变成数组的第 l 个到第 r ,最少总共需要几次操作。
比如数组l到r 是1,2,8,10,那总共需要0+1+3+4次操作

题解

数组中的每一个数组求出次数,然后构造前缀和,来应对静态区间查询。
直接从1开始构造数字会超时,实际上我们可以逆着构造,这样两个操作就变成

  • 1.将数字减一
  • 2.将数字除二

比如10,我们首先判断它是二的倍数所以10->5,5不是二的倍数所以5->4。
所以有 10->5->4->2->1

AC代码

typedef long long ll;
ll s[100008];
ll f[100005];
ll func(ll x) {
	ll ans = 0;
	for (; x!=1;x>>=1) {
		if (x & 1)ans ++;
		ans++;
	}
	return ans;
}

int main() {
	int t, n, q;
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &q);
		for (int i = 1; i <= n; i++) scanf("%lld", &s[i]);
		for (int i = 1; i <= n; i++) {
			f[i] = func(s[i]) + f[i - 1];
		}
		for (int i = 0; i < q; i++) {
			int l,r;
			scanf("%d%d", &l, &r);
			printf("%lld\n", f[r] - f[l-1]);
		}
	}
	return 0;
}

C Two-gram CodeForces - 977B

题意

给定字符串中找到出现最多的长度为2的子串,如AAABA,其中AA出现了2次。

题解

枚举所有长度为2的子串,找出出现最多的就好

AC代码

char s[200];
int vis[26 * 26+5];
int main() {
	int n;
	scanf("%d%s", &n,s);
	for (int i = 0; i < n-1; i++) {
		vis[(s[i] - 'A')*26+(s[i + 1] - 'A')]++;
	}
	int ans = 0;
	int max = 0;
	for (int i = 0; i <= 26 * 26; i++) {
		if (max < vis[i]) {
			ans = i;
			max = vis[i];
		}
	}
	printf("%c%c\n", ans / 26 + 'A', ans % 26 + 'A');
	return 0;
}

D Wrong Subtraction CodeForces - 977A

题意

给你 n 和 k,对 n 进行 k 次操作,操作为

  • 如果个位数是非零数那么减一
  • 如果个位数是零则除十
    求最后答案。(保证答案为正整数)

题解

k很小,无脑模拟。

AC代码

int main() {
	int n,k;
	scanf("%d%d", &n, &k);
	for (int i = 0; i < k; i++) {
		if (n % 10)n--;
		else n /= 10;
	}
	printf("%d\n", n);
	return 0;
}

E Eyad and Math Gym - 101502H

题意

判断 \(a^b\)\(c^d\)的大小

题解

高中数学
肯定不能直接算,数值太大。实际上两边同取log,比较下就好。

AC代码

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		int a, b, c, d;
		scanf("%d%d%d%d", &a, &b, &c, &d);
		if (b*log(a) < d*log(c)) 
			printf("<\n");
		else printf(">\n");
	}
	return 0;
}

F Card Constructions CodeForces - 1345B

题意

给你n张牌,搭金字塔,一次必须搭能搭的最大的塔,问你最后能搭几个塔。

题解

找规律打表。
将不同高度的金字塔消耗的卡牌都求出来,然后二分查找能搭的最大的。
(不用二分直接遍历也行,但理论上二分速度会快)

AC代码

int ta[30004];
int main() {
	int t, n;
	int a = 1, b = 0;
	for (int i = 1; i <= 25820; b += i, i++, a += i) {
		ta[i] = a * 2 + b;
	}

	scanf("%d", &t);

	while (t--) {
		scanf("%d", &n);
		int ans = 0;
		while (n >= 2) {
			int k = lower_bound(ta + 1, ta + 25821, n) - ta;
			if (ta[k] != n)k--;
			n -= ta[k];
			ans++;
		}
		printf("%d\n", ans);
	}

	return 0;
}

G Dima and Sequence CodeForces - 272B

题意

有函数\(f(x)\)

  • \(f(0) = 0\)
  • \(f(2·x) = f(x)\)
  • \(f(2·x + 1) = f(x) + 1\)

给你一个数组 a ,问你有其中多少对\((i, j) (1 ≤ i < j ≤ n)\)
使得\(f(a_i) = f(a_j)\).

题解

由于数组的值特别大达到1e9,所以不能直接对函数打表。和B题很像,我们可以逆推,来快速求出某个数的函数值,复杂度大概为\(O(logn)\)完全可以接受,计数部分就对逆推出来的函数值使用哈希方法,得出相同的数量,然后计数一下就好,如果有2个相同,那就1对,3个相同就3对,4个相同就3+2+1对,预处理下1+2+3+4...,就可以直接累加。

AC代码

int f(int x) {
	int ans = 0;
	while (x) {
		while (x&&x % 2 == 0)x /= 2;
		if (x) {
			x--;
			ans++;
		}
	}
	return ans;
}

int vis[100];
ll fac[100005];
int main() {
	int n,m,q;
	for (ll i = 1;i <=100000 ; i++ ) {
		fac[i] = fac[i - 1] + i;
	}
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &q);
		vis[f(q)]++;
	}
	long long ans = 0;
	for (int i = 0; i < 100; i++) {
		if (vis[i]>1)ans += fac[vis[i] - 1];
	}
	printf("%lld\n",ans);
}

H Moderate Modular Mode CodeForces - 1604D

题意

有两个偶数 \(x\)\(y\),满足 \(n\;mod\;x=y\;mod\;n\),求满足条件的任意 \(n\)

题解

  • \(x=y\) 时, \(n=x\)

  • \(x>y\)

    • 如果 \(n>y\) ,那么式子左边,也就是 \(y\;mod\;n=y\),易推出 \(n=kx+y\)
    • 如果 \(n≤y\) , 无解。
  • \(x<y\) 时,这个直推式子就比较麻烦了,但是可以确定 \(n\) 的范围 \([x,y]\),当 \(y=kx\) 时,\(x=y\);
    同时也可以确定余数 \(r\) 的范围 \([0,x)\),假设 \(kx<y<(k+1)x\),那么 \(n=kx+y2\) ,这里建议大家画一下图。

AC代码


int main(){
	int t;
	scanf("%d",&t);
	long long x,y;
	while(t--){
		scanf("%lld%lld",&x,&y);
		if(x>y){
			printf("%lld\n",x+y);
		}
		else{
			ll ans=y-y%x/2;
			if(ans%x==y%ans)printf("%lld\n",ans);
		}
	}

	return 0;
}
posted @ 2022-01-27 17:13  _comet  阅读(144)  评论(0编辑  收藏  举报