A. Polycarp and the Day of Pi
题意:给出字符串,让字符串与圆周率的前30位进行比对,输出字符串与圆周率正确匹配的字符数,字符串没有小数点
思路:设定const变量字符串,然后对输入字符串字符进行一一比对,并不断更新匹配到的字符长度,直到字符不相等或者到达字符串结尾,输出匹配到的长度
派的前30位题目已给出,字符串不超过30位
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
#include <stack>
#include <unordered_set>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vector<int>> vvi;
typedef vector<vector<ll>> vvll;
typedef vector<char> vc;
#define INT_MAX pow(2, 31) - 1
#define INT_MIN -pow(2, 31)
const string s = "314159265358979323846264338327";
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int N;
cin >> N;
while (N--){
string a;
cin >> a;
int rst = 0;
for (int i = 0; i < a.size(); ++i){
if (a[i] != s[i]){
break;
}
rst += 1;
}
cout << rst << endl;
}
return 0;
}
B. Taisia and Dice
题意:给定数字n和r,将r分解成n个数并且每个数不超过6,题目保证每个输入示例有输出。
思路:边界情况是n个数都为1或者n个数都为6。于是可以先建立一个长度为n的数组,然后依次对数组中的数加1,直到该数组的和为r,因为题目保证一定有答案,所以数组元素一定不会超过6。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
#include <stack>
#include <unordered_set>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vector<int>> vvi;
typedef vector<vector<ll>> vvll;
typedef vector<char> vc;
#define INT_MAX pow(2, 31) - 1
#define INT_MIN -pow(2, 31)
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int N;
cin >> N;
while (N--){
int n, s, r;
cin >> n >> s >> r;
cout << s - r << " " ;
n -= 1;
vi a(n, 1);
int sum = n;
for (int i = 0; sum < r; ++i){
a[i % n] += 1;
sum += 1;
}
for (auto x : a){cout << x << " ";}
cout << endl;
}
return 0;
}
总结:一开始看到这个题目的时候想到的是将将r平均分配给n个数,然后总和如果不够r再网上补,但是发现如果采用这种建立规则的编程方式,会出现很多特殊情况,于是只能采用这种暴力破解的方法。
C. Premutation
题意:感觉题目应该是permutation。 有一个原始数组,长度为n,并且是乱序的permutation数组。现给出n个输入,每个输入中将去除原始数组中任意一位的元素,并且保证每个输入都不重复。根据这些输入推出原始数组。
思路:题目给出的输入中,每个输入都是缺少了一位,那么如果丢失的是起始位,或者末位,就只需要将该输入的起始位跟末位补上即可。而对于起始位跟末位而言,输入的示例中出现的次数一定超过1次,而且只有一个数字符合条件,那么只要找出输入示例中的这个位,然后再标记输入中起始位不是首位的情况,将起始位跟这个输入输出即是答案。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
#include <stack>
#include <unordered_set>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vector<int>> vvi;
typedef vector<vector<ll>> vvll;
typedef vector<char> vc;
#define INT_MAX pow(2, 31) - 1
#define INT_MIN -pow(2, 31)
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int N;
cin >> N;
while (N--){
int n;
cin >> n;
vvi a(n, vi(n - 1));
set<int> sett;
int first_num;
for (int i = 0; i < n; ++i){
for (int j = 0; j < n - 1; ++j){
cin >> a[i][j];
if (j == 0){
if (sett.count(a[i][j])){first_num = a[i][j];}
sett.insert(a[i][j]);
}
}
}
for (int i = 0; i < n; ++i){
if (a[i][0] != first_num){
cout << first_num << " ";
for (int j = 0; j < n - 1; ++j){ cout << a[i][j] << " \n"[j == n - 2];}
}
}
}
return 0;
}
总结:做题太少,一时半会找不到思路。一开始想的是将每个输入进行比对,确定出每个数所在的位,但是工程量有点大,而且中间的缺失位前后次序不好确定。然后想到如果只丢失起始位的话,其他的位是有序的,而第一位的数字很好确定。
D. Matryoshkas
题意:给定一个数组,数组中存在很多数字,将这些数字串成串,在串尽可能少的情况下将所有数字都包含进去。每个串相邻的数字差值为1,输出最少串的数量。
思路:用有序的map存储每个数字出现的次数,如果当前数字x出现的次数为y次,且数字x-1出现的次数为z次,那么数字x可以生成max(0, y-z)个新的串。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
#include <stack>
#include <unordered_set>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vector<int>> vvi;
typedef vector<vector<ll>> vvll;
typedef vector<char> vc;
#define INT_MAX pow(2, 31) - 1
#define INT_MIN -pow(2, 31)
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int N;
cin >> N;
while (N--) {
int n, rst = 0;
cin >> n;
map<int, int> mapp;
for (int i = 0; i < n; ++i){
int tmp;
cin >> tmp;
mapp[tmp] += 1;
}
for (auto[x, y] : mapp){
rst += max(0, y - mapp[x - 1]);
}
cout << rst << endl;
}
return 0;
}
总结:该题目很搞,一开始想到的解决方法是利用哈希表存储数字区间,如果新加入的数字可以并到区间中,那么将这个区间扩大,最后保留的区间数就是串的数,结果发现在制定规则的过程中有一些不可控因素,然后网上借鉴大佬们的方法解出来的题目。该题目的tag有数据结构跟贪心算法,数据结构的话可能就是涉及哈希map相关的知识,贪心的话应该就是在遍历map的时候串的选择策略以及对最终串的数量的影响,是个启发很大的题目。