今天是大家喜欢()的数学场
- 简单 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;
}