• 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;
    }
    
  • 相关阅读:
    word count
    第三周作业:Visual Studio 2013
    第三周作业:读程序
    只有动手才能发现问题
    软件工程
    final个人阅读作业
    个人阅读作业7
    第一次个人项目修改
    结对编程项目总结(王开207, 唐彬170)
    个人博客作业3
  • 原文地址:https://www.cnblogs.com/komet/p/15850425.html
Copyright © 2020-2023  润新知