第一题 手机
样例
i have a dream
思路
这题考点就是怎么存储手机键盘,这里我选择用一个二维字符串来存储,一维存储每一个键。
code
#include<bits/stdc++.h>
using namespace std;
//string str = "abc def ghi jkl mno pqrs tuv wxzy";
const string str[] = { {' '}, {"abc"},{"def"},{"ghi"},{"jkl"},{"mno"},{"pqrs"},{"tuv"} ,{"wxyz"},{"*"},{"#"}};
int cnt;
int main()
{
string s; getline(cin,s);
for (int i = 0; i < s.size(); i++)
{
for (int j=0;j<13;j++)
{
for (int k = 0; k < str[j].size(); k++)
{
if (s[i] == str[j][k])
{
cnt += k+1;
break;
}
}
}
//if (s[i] == ' ')cnt++;
}
cout << cnt << endl;
return 0;
}
第二题 幸运树
样例
2
16347
76344
解题思路
纯模拟,按照题意模拟即可。
//第二题
#include<bits/stdc++.h>
using namespace std;
#define int long long
int Sum(int x)
{
int sum = 0;
while (x)
{
sum += x % 10;
x /= 10;
}
return sum;
}
int solve(int temp)
{
int sum = 0;
//把数乘以7
temp *= 7;
while (1)
{
if (temp > 9)
{
sum = Sum(temp);
}
else
{
return temp;
}
temp = sum;
}
}
signed main()
{
cin.tie(nullptr)->sync_with_stdio(false);
int t; cin >> t;
while (t--)
{
string x; cin >> x;
reverse(x.begin(), x.end());
string s;
for (int i = 0; i < x.size(); i++) //因为下标从0开始,所以题目中的对奇数位进行操作这里是对偶数位进行操作
{
if (i % 2 == 0)
{
int t = solve(x[i] - '0');
//cout << "x[i]: " << x[i] <<" "<<"t: "<<t<< endl;
stringstream ss;
ss << t;
ss >> x[i];
}
}
stringstream ss;
ss << x;
int num;
ss >> num;
int ans = Sum(num);
if (ans % 8 == 0)cout << "T" << endl;
else cout << "F" << endl;
}
return 0;
}
第三题 a+b problem
思路
就是考大数相加
样例
1
1
1001
9099
写了一坨狗屎:
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
void slove(string a, string b)
{
int jin = 0;
string sum(a);
for (int i = 0; i < a.size(); i++)
{
int num= (a[i] - '0') + (b[i] - '0') + jin;
// stringstream ss;
//string str;
//ss<<num;
//ss >> str;
//
if (num > 9)
{
sum[i] = num % 10;
jin +=1;
}
else
{
stringstream ss;
ss << num;
ss >> sum;
}
}
//cout << sum.size() << endl;
for (int i = 0; i < sum.size(); i++)
{
cout << sum[i]<<" ";
}
}
signed main()
{
cin.tie(nullptr)->sync_with_stdio(false);
string a, b;
cin >> a >> b;
//补0
if (a.size() < b.size())
a.append(b.size() - a.size(), '0');
else
a.append(a.size() - b.size(), '0');
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
//开始大数相加
slove(a, b);
return 0;
}
正确代码:
#include<bits/stdc++.h>
using namespace std;
vector<int> sum(vector<int>& a, vector<int>& b)//引用是为了提高效率,尽可能不调用拷贝构造
{
vector<int>c;
int t = 0;
for (int i = 0; i < a.size() || i < b.size(); i++)
{
if (i < a.size())t += a[i];
if (i < b.size())t += b[i];
c.push_back(t%10); //比如个位数 5+1=6 6/10=0,说明不用进位 如果9+9=18,18/10=1,说明需要进1位
t /= 10;
}
if (t)c.push_back(1);
return c;
}
int main()
{
string a, b; cin >> a >> b;
vector<int>v1, v2;
for (int i = a.size() - 1; i >= 0; i--)
v1.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--)
v2.push_back(b[i] - '0');
vector<int> c=sum(v1,v2);
for (int i = c.size() - 1; i >= 0; i--)
cout << c[i];
return 0;
}
第四题 求a的b次方
样例
2 3
样例
7 2011
思路
我刚开始用的快速幂,过了第一个样例,第二个样例就溢出了
#include<bits/stdc++.h>
using namespace std;
#define int long long
int qmi(int a,int b)
{
int res = 1;
while (b) //b如果不为0
{
res = res * a ;
a = a * a; //底数倍增
b >>= 1; //指数右移
}
return res;
}
signed main()
{
int a, b; cin >> a >> b;
int ans = qmi(a, b);
//cout << ans<<endl;
string str = to_string(ans);
while (str.size() < 3)str = '0' + str;
for (int i = 0; i < 3; i++)
{
cout << str[i];
}
return 0;
}
我以为是b太大了,long long也存不下,要用字符串快速幂,类似于这题:2024年第八场蓝桥杯小白赛 djwcb 知识点:快速幂 - 掘金 (juejin.cn)
但是实际上b只有10000,是可以存下的,错误的原因是板子默错了,痛失一道题:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int qmi(int a, int b,int p)
{
int res = 1;
while (b) //b如果不为0
{
if(b&1)res = res * a%p;
a = a * a%p; //底数倍增
b >>= 1; //指数右移
}
return res;
}
signed main()
{
int a, b; cin >> a >> b;
int ans = qmi(a, b,1000);
//cout << ans<<endl;
string str = to_string(ans);
while (str.size() < 3)str = '0' + str;
for (int i = 0; i < 3; i++)
{
cout << str[i];
}
return 0;
}
第五题 赛前准备
思路
要满足K次兴奋,首先k不能大于n,因为总共就n个数,不可能有k+1次兴奋。
k如果为0的话就是全部升序,k如果为n的话就是全部降序。
想要兴奋k次,就让前面面1全部升序,直到k次,后面全部降序即可。
样例
3
6 2
5 4
5 0
code
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t; cin >> t;
while (t--)
{
int n, k; cin >> n >> k;
int l = 1, r = n;
for (int i = 1; i <= k; i++)cout<<l++;
for (int j = k + 1; j <=n; j++)cout << r--;
cout << endl;
}
return 0;
}
第六题 最小乘积
思想 只需要记录一下正数,负数,0,的数量即可。
如果存在 0,显然不管怎么操作最后乘积都是0,则不需要操作。
如果不存在 0,若 负数 有奇数个,那么最终乘积为负数,不需要修改。
若 负数 有偶数个,那么乘积一定正数,任意一个改成0。
code
#include<bits/stdc++.h>
using namespace std;
int n;
void solve()
{
int xiao = 0, da = 0, deng = 0;
cin >> n;
for(int i=0;i<n;i++)
{
int x; cin >> x;
if (x < 0)xiao++;
else if (x == 0) deng++;
else da++;
}
//如果存在一个0,结果一定为0
if (deng >= 1) cout << 0 << endl;
else
{
if (xiao % 2) //奇数个负数,最后乘积为负数
cout << 0 << endl;
else //偶数个负数,乘积为正数,把任意改为0
{
cout << 1 << endl;
cout << 1 << " " << 0 << endl;
}
}
}
int main()
{
int t = 1; cin >> t;
while (t--)
{
solve();
}
return 0;
}
第七题 探险
思路 这道题类似于20204年第三场小白赛 怪兽突击 知识点:贪心 - 掘金 (juejin.cn)。
小理一定在某个洞穴停下,剩下的次数全部用来反复进入前面进入过的洞穴,且反复进入的洞穴一定是同一个,经验值最大的那一个。
那么只需要枚举所有情况就可以了。
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n, k;
void solve()
{
cin >> n >> k;
vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i++)cin >> a[i];
for (int j = 1; j <= n; j++)cin >> b[j];
//枚举每个洞穴经历k次之后的经验值
//所有经验值里面取一个最大值
int f = 0, res = 0, ans = 0;
for (int i = 1; i <= min(n, k); i++)
{
int remain = k - i;
f += a[i];
//剩下的k-1次全部打当前洞穴
res = max(res, b[i]);
ans = max(ans,remain*res+f);
}
cout << ans << endl;
}
signed main()
{
int t; cin >> t;
while (t--)
{
solve();
}
return 0;
}
第十题 去除没有吸引力的配对
思路
从前往后遍历字符串s,如果两个字符不一样那就可以删除,我们把这两个字符标记为1,然后把没有标记为1的字符加入到temp字符串里,用temp字符串更新s字符串。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int flag[N];
int n;
string temp;
int solve(string s)
{
while (1)
{
for (int i = 0; i < s.size() - 1; i++)
{
if (s[i] != s[i + 1] && flag[i] == 0)
{
flag[i] = flag[i + 1] = 1;
}
}
for (int i = 0; i < s.size(); i++)
{
if (flag[i] == 0)
{
temp.push_back(s[i]);
}
}
cout << temp << endl;
s = temp;
temp.clear();
memset(flag,0,sizeof flag);
if (s.size() == 0)break;
int cnt = 0;
for (int i = 0; i < s.size()-1; i++)
{
if (s[i] != s[i + 1])cnt++;
}
if (cnt == 0)break;
}
return s.size();
}
signed main()
{
int t; cin >> t;
while (t--)
{
cin >> n;
string s; cin >> s;
cout <<"答案:"<< solve(s) << endl;
}
return 0;
}
代码存在的问题是只考虑了从前向后依次遍历字符串,比如:
dabbb
'd'和'a'不一样删除,变为:
bbb
不能再删除了。但是实际上,这个顺序并不一定是从前向后遍历的,比如可以先把'a'和'b'删除,变为:
abb
然后再把a,b删除,还剩:
b
正解
如果一个数出现的次数最多,且刚好出现的次数为n的一半,那么肯定会有另外一半数与它匹配,最后全部消掉。如果这个数出现的次数超过了一半,因为这个数出现的最多,我们就叫maxn,因为出现的超过了n的一半,所以剩下的数肯定不够与它匹配,那么消除完之后还剩的个数就是maxn-(n-maxn)。否则,出现这个数出现的次数少于n的一半,假设它出现了奇数次,那么消到最后会剩一个,如果它出现的次数为偶数,那么消到最后会全部消完。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t; cin >> t;
while (t--)
{
int n; cin >> n;
string s; cin >> s;
int cnt[26] = { 0 };
int maxn = 0;
for (int i = 0; i < n; i++)
{
cnt[s[i] - 'a']++;
maxn = max(maxn, cnt[s[i] - 'a']);
}
if (maxn >= n - maxn)cout << maxn - (n - maxn)<<endl;
else cout << (n & 1) << endl;
}
return 0;
}