目录
题解——zzh
7-2 L2-求求别再发表情包了!
小c是某聊天平台上的一活跃用户,他非常喜欢根据自己的心情发一些奇奇怪怪的表情包。如小c今天的心情指数为k,他会发给别人2k−1条消息。 第一条信息包含一个表情,第二条信息包含两个表情… , 第k条信息包含k个表情,k+1条信息包含k-1个表情,… 最后一行是一个表情。
如果小c今天的心情指数为3,他就会向下面这样发送表情包
当然,对方也是有心情的,对方的那个用户会根据自己的心情选择接受表情包的数量,当发送的表情包总数量到达一定的值时,对方会选择将小c拉黑。例如如果对方的心情指数为m时,其会在收到表情包的数量大于等于m时将小c拉黑。
现在小c想知道自己被拉黑之前发了多少条信息,注意是多少条信息而不是表情包的数量。
例如:
输入格式:
首先输入一个数字t,为测试样例的组数1<=t<=100
每组样例包括一行正整数k,m,即小c的心情指数和对方的心情指数。(k<=10^9,m<=10^18)
输出格式:
输出小c被拉黑前共发送了多少条信息,
输入样例:
7
4 6
4 7
1 2
3 7
2 5
100 1
1000000000 923456789987654321
输出样例:
在第一个测试用例中,小c分别写了三条包含1、2和3个表情的消息,由于1+2+3≥6,之后小c就被拉黑了。
在第二个测试案例中,小c写了4条消息,分别包含1、2、3和4个表情,因为1+2+3+4≥7,之后小c就被拉黑了。
3
4
1
4
3
1
1608737403
思路:
此题数太大,暴力写题会超时,用数组会超内存,不如使用二分查找。
代码实现:
1.首先读题可知,从1到K是一个等差数列,从K到2*K-1也是一个等差数列,所以可以用函数来表示二分查找时mid对应要比较的值。
#include <stdio.h>
long long k, m; //定义为全局变量,以便使用
int num(long long x) {
if (x < k)
return (x * (x + 1)) / 2 < m; //小于K时的前x项和
else
return (k * (k + 1)) / 2 + (k - 1) * (x - k) - ((x - k) * (x - k - 1)) / 2 < m;
} //大于K时的前X项和
2.完成二分算法。
void search() {
scanf("%lld %lld", &k, &m);
long long l = 1, r = 2 * k - 1, mid;
while (l < r) {
mid = l + (r - l) / 2;
if (num(mid))
l = mid + 1;
else
r = mid;
}
printf("%lld\n", l);
}
3.主函数。
int main() {
int t;
scanf("%d", &t);
while (t--) {
search();
}
return 0;
}
A - A + B Problem II
有一天,松松写完了Java项目想来VJ刷题来完成每日一题任务,这时候他看到了一道A+B problem,松松想这不有手就行?于是他十秒钟就敲出了代码,但是却WA了,你能帮帮他吗?
Input
输入数据的第一行为一个整数T(1≤T≤20),表示测试数据总数,紧接着的T行数据,每行包含由空格隔开的两个整数a和b,每组数据占一行。注意了,a和b可能非常大,大到超过32位整数可以表示的范围,我们假定a和b的位数不超过1000。
Output
对于每组数据,你需要输出两行,第一行显示"Case #:"(注意输出为英文字符),第二行为一个等式"a + b = Sum",这里的Sum就是指a + b的结果(注意这个等式中的空格)。请在每两组输出数据间输出一个空行。
Sample Input
2
1 2
112233445566778899 998877665544332211
Sample Output
Case 1:
1 + 2 = 3
Case 2:
112233445566778899 + 998877665544332211 = 1111111111111111110
思路:
此题为高精度计算题,由于数字太大,因考虑使用字符串来表示输入的数字。
代码实现:
#include <stdio.h>
#include <string.h>
int main() {
char a[1000], b[1000], c[1001];
int t = 1, n;
scanf("%d", &n);
while (n--) {
scanf("%s %s", a, b);
printf("Case %d:\n", t);
printf("%s + %s = ", a, b);
t++;
int i = strlen(a) - 1, j = strlen(b) - 1, l = 0, k = 0;//定义i,j以便从个位开始加
for (; i >= 0 && j >= 0; i--, j--) {
int m = a[i] - '0' + b[j] - '0' + k;
k = m / 10; //k为a,b各个位数相加后的进位
c[l++] = m % 10; //取余得值
}
while (i >= 0) { //再算一遍数组a与b,以免a,b位数不同
int m = a[i--] - '0' + k;
k = m / 10;
c[l++] = m % 10;
}
while (j >= 0) {
int m = b[j--] - '0' + k;
k = m / 10;
c[l++] = m % 10;
}
if (k)
c[l++] = k;
while (l--)
printf("%d", c[l]);
printf("\n");
if (n != 0)
printf("\n"); //注意格式
}
return 0;
}
G - 回文数猜想
一个正整数,如果从左向右读(称之为正序数)和从右向左读(称之为倒序数)是一样的,这样的数就叫回文数。任取一个正整数,如果不是回文数,将该数与他的倒序数相加,若其和不是回文数,则重复上述步骤,一直到获得回文数为止。例如:68变成154(68+86),再变成605(154+451),最后变成1111(605+506),而1111是回文数。于是有数学家提出一个猜想:不论开始是什么正整数,在经过有限次正序数和倒序数相加的步骤后,都会得到一个回文数。至今为止还不知道这个猜想是对还是错。现在请你编程序验证之。
Input
每行一个正整数。
特别说明:输入的数据保证中间结果小于2^31。
Output
对应每个输入,输出两行,一行是变换的次数,一行是变换的过程。
Sample Input
27228
37649
Sample Output
3
27228--->109500--->115401--->219912
2
37649--->132322--->355553
思路:
此题可以用先用一个数组将变化前后的数值记录,再函数判断回文数并增加次数,直到得到回文数。
代码实现:
#include <iostream>
using namespace std;
int huiwen(int x, int y) {
int sum = 0, z = x;
while (z) {
sum = sum * 10 + z % 10; //判断回文
z /= 10;
}
y = sum;
return sum;
}
int main() {
int a;
while ((scanf("%d", &a)) != EOF) {
int s[100], n = 0, l = 1;
s[0] = a; //记录最初值
while (1) {
if (a == huiwen(a, n))
break;
else {
a += huiwen(a, n);
s[l++] = a; //记录变化后的值
}
}
cout << l - 1 << endl;
for (int i = 0; i < l - 1; i++) {
cout << s[i] << "--->";
}
cout << s[l - 1] << endl;
}
return 0;
}
本周总结:
1.本周主要学习了C++的入门,并使用C++完成了几道题目。
2.百词斩APP记单词
不足:虽然本周学习时间相比前2周上升很多,但有两次晚自习中途没有集中精力学习,浪费了时间,下周一定要改正。