声明:里面的算法是自己思考得来,没有进行网判。思路不对,代码错误还请指正。
第一题:小y删数字
给定一个长度为n的数组,数组元素为a1, a2, . . , an,每次能删除任意a的任意一位,求将所有数字变成0最少需要几步。 例如103若删除第1位则变成3;若删除第2位则变成13;若删除第3位则变成10。 输入描述 第一行一个正整数n代表数组长度。接下来一行n个数第j个数代表a。
1≤n ≤10^5 0≤ai≤10^9
输出描述
输出一行一个数代表答案。 示例1 输入
5
10 13 22 100 30
输出
7
思路与代码
统计不是0的数位个数。
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
cin>>n;
int ans = 0;
for(int i=0;i<n;i++){
int x = 0;
cin>>x;
while (x)
{
if(x%10) ans++;
x = x/10;
}
}
cout<<ans<<endl;
return 0;
}
第二题:小红的字符串切割
小红拿到了一个字符串,她希望你帮她切割成若干子串,满足以下两个条件:
子串长度均为不小于3的奇数。
子串内部的字符全部相同。
输入描述
第一行输入一个正整数n,代表字符串长度。第二行输入一个字符串,仅由小写字母组成。1 <n ≤200000 输出描述 如果无解,请输出-1。 否则按顺序输出若干个字符串,用空格隔开。
示例1
输入
8
aaabbbbb
输出
aaa bbbbb
思路与代码
将其分成块为3的,因此最后只能剩0,1,2这3种情况,因此再往前吸收,而发现只有余1的时候往前吸收两次,注意特判。
#include<iostream>
#include<unordered_map>
#include<vector>
using namespace std;
int main(){
int n = 0;
cin>>n;
vector<vector<int> > ans;
std::string temp;
cin>>temp;
for(int i=0;i<temp.size();){
int right = i+1;
while (right<temp.size()and temp[right] == temp[i])
{
right++;
}
if(right-i<3) {
cout<<-1;
return 0;
}
if (right-i == 4)
{
cout<<-1;
return 0;
}
// 如果是偶数需要拆分
if(((right-i)&1) == 0){
// 需要拆分成两个大于3的奇数
int j = i;
for(;j+3<=right;j++){
ans.push_back(vector<int>{j, j+3});
}
ans[ans.size()-1][1]+=right-j;
if((ans[ans.size()-1][1]-ans[ans.size()-1][0]&1) == 0){
// 就要往后吸收了
int index = ans.size()-2;
ans[index][1] = ans[ans.size()-1][1];
ans.pop_back();
}
}else{
ans.push_back(vector<int>{i, right});
}
i = right;
}
// 最后根据然后输出
for(auto&it:ans){
cout<<temp.substr(it[0], it[1]-it[0])<<" ";
}
cout<<endl;
return 0;
}
第三题:小红的数字匹配
定义一个“模板串”为一个由数字字符和′?"组成的字符串。我们可以通过将问号替换成数字字符来得到正整数。显然,一个模板串可能会和多个正整数匹配。例如: “1?2"可以和102或者132等正整数匹配。请注意,匹配的正整数不能包含前导零,例如”??1"可以匹配101,但不能匹配001。 小红拿到了一个模板串,她想知道,和这个模板串匹配的正整数中,第k小的是多少?
输入描述
第一行输入一个正整数t,代表询问次数。接下来的2* t行,每两行为一次询问: 第一行输入一个字符串,仅由数字字符和?'组成。第二行输入一个正整数k,代表询问的是第k小。
1≤t ≤ 10^4 1≤k≤10 ^9
字符串长度不超过30。
输出描述
输出t行,每行输出一个答案。 如果一共都没有k个匹配的正整数,则输出-1。否则输出第小的匹配的正整数。
示例1
输入
4
??1
1
22?
100000000
2??
3
000???
1
输出
101
-1
202
-1
思路与代码
此题就这样思考比如
看例子:??8??
,k=3
。那么我们匹配得来的最小的数字是8所在数位定了,其他位置要么是1-9,要么是0-9,因此,可以直接把8位去掉,得。4位?,然后注意?的数字范围,得到这四位数字的最小值和最大值,然后网上加k-1,如果超过最大值直接返回-1,否则得到的结果就是对应?号的数位结果,位置复原,就是最终的结果。
比如上述例子:
最小值是数位拿出来1000。加上3-1=2得1002 。8位复原10802。就是最终的结果。
#include<iostream>
#include<string>
using namespace std;
int main(){
int n = 0;
int k = 0;
cin>>n;
while (n--){
string temp;
cin>>temp;
if(temp[0] == '0'){
cout<<-1<<endl;
continue;
}
cin>>k;
int bits = 0;
for(int i=0;i<temp.size();i++){
if(temp[i] == '?') bits++;
}
int bits2 = bits;
int lower = 0;
int hight = 0;
if (temp[0] == '?')
{
lower = pow(10, bits-1);
hight = 9;
bits--;
while(bits--){
hight = hight*10+9;
}
}else{
lower = 0;
hight = 9;
bits--;
while(bits--){
hight = hight*10+9;
}
}
if(lower+k > hight){
cout<<-1<<endl;
continue;
}else{
lower+=k-1;
}
std::string cur = to_string(lower);
std::string cur_ = "";
cur_.append(bits2-cur.size(),'0');
cur_.append(cur);
int index = 0;
std::string ans = "";
for(int i=0;i<temp.size();i++){
if(temp[i] == '?'){
ans.push_back(cur_[index++]);
}else{
ans.push_back(temp[i]);
}
}
cout<< ans<<endl;
}
return 0;
}