总的来说,作为暑期实习生的题目,三题都不难,仔细思考都能顺利做出来
PS:我喜欢漂亮点的代码风格O(∩_∩)O
对于A题,求个逆序,再求最长公共子序列就可以了,这里回头还可以复习一下最长公共子串怎么求,记得上次省赛线段树+最长公共子串那题挂了不少人。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int MAXLEN = 1010;
int temp[MAXLEN][MAXLEN];
int getRemoveNumber(const string& res, int len)
{
string str(res);
reverse(str.begin(), str.end());
for (int i = 0; i < len; ++i)
{
for (int j = 0; j < len; ++j)
{
if (res[i] == str[j])
temp[i + 1][j + 1] = temp[i][j] + 1;
else temp[i + 1][j + 1] = max(temp[i + 1][j], temp[i][j + 1]);
}
}
return len - temp[len][len];
}
int main()
{
string str;
int ans;
while (cin >> str)
{
ans = getRemoveNumber(str, str.length());
cout << ans << endl;
}
return 0;
}
对于B题:设置两个下标,从后往前找就可以了,不难但容易出错,而且加上边界情况容易混乱
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void solve(string& str, int len)
{
int i = len - 1, j = len - 1;
char temp;
while (true)
{
if (i < 0)
{
return;
}
if (str[i] < 'a')
{
temp = str[i];
for (int k = i + 1; k <= j; ++k)
{
str[k - 1] = str[k];
}
str[j] = temp;
j--;
}
i--;
}
}
int main()
{
string str;
while (cin >> str)
{
solve(str, str.length());
cout << str << endl;
}
return 0;
}
对于C题:咋一看简单,细想却发现不少问题。首先对于A、B两个数,求它们的对数,有两种情况,一种是A==B,则公式为NUM(A)*(NUM(A)-1) / 2,另一种,A != B时,公式为NUM(A)*NUM(B)。然后对于最小差的对数,也分两种情况,一方面是含有相同的数字的情况,那么最小差肯定是0,假设A有nA个相同的,B有nB个相同的,则最小差是它们的总和。另一方面,不含有相同的数字,即N个数各不相同,这也好办,代码中我注释了,就不罗嗦了,当然这两个方面可以合在一起,但要注意比较,不要在遍历时重复计算两个相同的。。。最后在降复杂度上,可以发现可以着手的地方是计算每个数字出现的个数上,可以用map降为O(1),当然,这一步一开始就因该想到了( •̀ ω •́ )y。
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
const int MAX = 2147483647;
map<int, int>mmap;
int arr[100100];
int countNumber(int a, int b)
{
if (a == b) return mmap[a] * ( mmap[a] - 1 ) / 2;
else return mmap[a] * mmap[b];
}
int main()
{
int N;
while (cin >> N)
{
if (N == 1)
{
cin >> N; //随便读一个进来
cout << "0 0" << endl;
continue;
}
for (int i = 0; i < N; ++i)
{
cin >> arr[i];
mmap[arr[i]]++;
}
sort(arr, arr + N);
//若含有差值为0的,则看有多少个这样的数字,把它们的总对数加起来就是差值最小的对数
int minNum1 = 0;
for (auto it = mmap.begin(); it != mmap.end(); ++it)
{
if (it->second > 1)
{
minNum1 += ( it->second )*( it->second - 1 ) / 2;
}
}
if (minNum1 != 0)
{
cout << minNum1 << " " << countNumber(arr[0], arr[N - 1]) << endl;
mmap.clear();
continue;
}
//下面是不含有重复数字的,取差最小的两个数和差最大的两个数
int min1, min2, mmin = MAX;
//int max1, max2, mmax = INT_MIN; //23333,突然发现用不着。。。
int minNum2 = 0, maxNum2 = 0;
for (int i = 0; i < N - 1; i++)
{
//找最小
if (arr[i + 1] - arr[i] < mmin)
{
//min1 = arr[i]; //同上,用不着。。。
//min2 = arr[i + 1];
mmin = arr[i + 1] - arr[i];
minNum2 = countNumber(arr[i], arr[i + 1]);
}
else if (arr[i + 1] - arr[i] == mmin)
{
minNum2 += countNumber(arr[i], arr[i + 1]);
}
}
cout << minNum2 << " " << countNumber(arr[N - 1], arr[0]) << endl;
mmap.clear();
}
return 0;
}