目录
第一题:小乐乐改数字
题目链接:小乐乐改数字_牛客题霸_牛客网
描述
小乐乐喜欢数字,尤其喜欢0和1。他现在得到了一个数,想把每位的数变成0或1。如果某一位是奇数,就把它变成1,如果是偶数,那么就把它变成0。请你回答他最后得到的数是多少。
输入描述:
输入包含一个整数n (0 ≤ n ≤ 10^9)
输出描述:
输出一个整数,即小乐乐修改后得到的数字。
示例1
输入:
222222
输出:
0
简单模拟题。字符串读进来然后在去遍历修改即可。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
cin >> s;
for(int i = 0; i < s.size(); i++)
{
int num = s[i] - '0';
if(num % 2 == 0) s[i] = '0';
else s[i] = '1';
}
int ans = stoi(s);//这个函数会处理前导零
cout << ans << endl;
return 0;
}
第二题:十字爆破
题目链接:登录—专业IT笔试面试备考平台_牛客网
牛牛在玩一个游戏:
一共有n行m列共n*m个方格,每个方格中有一个整数。
牛牛选择一个方格,可以得到和这个方格同行、同列的所有数之和的得分。
例如:对于一个2*2的方格:
1 2
3 4
牛牛选择每个方格的得分如下:
6 7
8 9
因为1+2+3=6,1+2+4=7,1+3+4=8,2+3+4=9。
现在牛牛想知道下一步选择每个格子的得分情况,你可以帮帮他吗?
输入描述:
第一行有两个正整数 n n\ n 和 m m\ m ,代表方格的行数和列数。 (1≤n∗m≤1000000) (1≤n*m≤1000000)\ (1≤n∗m≤1000000)
接下来的 n n\ n 行,每行有 m m\ m 个数 aija_{ij}aij,代表每个方格中的整数。 (−109≤aij≤109) (-10^9≤a_{ij}≤10^9)\ (−109≤aij≤109)
输出描述:
输出 n 行 m 列整数,分别代表选择每个位置方格的得分情况。
示例1
输入
2 2 1 2 3 4
2 2
1 2
3 4
输出
6 7 8 9
6 7
8 9
题目的意思就是输出每个位置所在行和列的总和。很容易想到暴力解法——每遍历到一个元素就去计算它所在行和所在列的和。这里我也不卖关子了,会超时。我们需要对数组进行一个预处理。需要开两个数组,一个row[ ]用来存储每一行的和,另一个col[ ]用来存储每一列的和。这样,在遍历到(i,j)这个元素的时候,我们直接去存储行之和的数组和存储列之和的数组了拿数据就可以了,减少了很多计算。以(i,j)元素为例,该位置对应的得分就是row[i] + col[j] - arr[i][j],之所以要减掉 arr[i][j]是因为加了两次。最后注意数据范围即可。
#include <iostream>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
LL row[N], col[N];//存储每行的和/存储每列的和
int main()
{
int n, m;
cin >> n >> m;
vector<vector<LL>> arr(n, vector<LL>(m, 0));//存储输入的数组
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
cin >> arr[i][j];
row[i] += arr[i][j];//把该数添加到第i行上
col[j] += arr[i][j];//把该数添加到第j列上
}
}
//计算每一个位置的得分
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
LL cnt = row[i] + col[j] - arr[i][j];
cout << cnt << " ";
}
cout << endl;//输出一行后换行
}
return 0;
}
第三题:比那名居的桃子
题目链接:登录—专业IT笔试面试备考平台_牛客网
题目描述
小红有一天看到了一只桃子,由于桃子看上去就很好吃,小红很想把它吃掉。
已知吃下桃子后,每天可以获得 ai的快乐值,但是每天会获得 bi的羞耻度。桃子的持续效果一共为 k 天。
小红想知道,自己在哪一天吃下果实,可以获得尽可能多的快乐值?
如果有多个答案获得的快乐值相等,小红希望获得尽可能少的羞耻度。
如果有多个答案的快乐值和羞耻度都相等,由于小红实在太想吃桃子了,她希望尽可能早的吃下桃子。
输入描述:
第一行有两个正整数 n 和 k ,分别代表桃子的有效期总天数,以及桃子效果的持续天数。
(桃子的有效期是指,无论桃子在何时服用,桃子的特殊效果只在这段时间之内有效)
第二行有 n 个正整数 ai ,分别代表每天可以获得的快乐值。
第三行有 n 个正整数 bi ,分别代表每天可以获得的羞耻度。
1≤k≤n≤10^5
1≤ai,bi≤10^9
输出描述:
一个正整数,代表小红是第几天吃下桃子的。
示例1
输入
4 2
3 5 1 7
4 6 5 1
输出
3
说明
选择在第三天吃下桃子,可以获得8快乐值和6羞耻度。
以示例1作说明。h表示存储快乐值的数组,s表示存储羞耻度的数组。
如果第一天吃下,快乐值会持续两天(k = 2),快乐值总和为8(第一天获得快乐值为3,第二天获得快乐值为5),羞耻度总和为10.
如果第二天吃下,快乐值会持续两天(k = 2),快乐值总和为6,羞耻度总和为11.
如果第三天吃下,快乐值会持续两天(k = 2),快乐值总和为8,羞耻度总和为6.
综上,第一天吃或者第三天吃得到的快乐值最大,但是第三题吃羞耻度会小于第一天吃,所以最终选择第三天吃。通过上面的演示,可以看到这题就是一道固定长度的滑动窗口问题,窗口长度为k(效果持续的天数)。
滑动窗口的一般做法:
1)进窗口
2)判断
3)出窗口
4)更新结果
最后就是注意数据的范围,int会溢出。
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
LL h[N], s[N];//分别存储快乐值和羞耻度
int main()
{
int n, k;
cin >> n >> k;
for(int i = 0; i < n; i++) cin >> h[i];//存储快乐值
for(int i = 0; i < n; i++) cin >> s[i];//存储羞耻度
int left = 0, right = 0, begin = 0;//begin记录哪天吃
LL max_h = 0, min_s = 0;//分别表示最大快乐值和最小羞耻度
LL sum_h = 0, sum_s = 0;//分别表示窗口内快乐值的和与羞耻度的和
//滑动窗口常规操作
while(right < n)
{
//进窗口
sum_h += h[right];
sum_s += s[right];
//判断和出窗口
while(right - left + 1 > k)
{
sum_h -= h[left];
sum_s -= s[left];
left++;
}
//更新结果
if(right - left + 1 == k)
{
//如果当前窗口内的快乐值大于前面
//记录的最大快乐值,肯定要更新
if(sum_h > max_h)
{
max_h = sum_h;
min_s = sum_s;
begin = left;
}
//如果当前窗口内的快乐值等于前面记录的
//最大快乐值,但是羞耻度较小,也要更新
else if(sum_h == max_h && min_s > sum_s)
{
max_h = sum_h;
min_s = sum_s;
begin = left;
}
}
right++;
}
//下标从0开始,天数从1开始
cout << begin + 1 << endl;
return 0;
}