更好的阅读体验:http://www.abmcar.top/archives/codeforcesround762div3
完整源代码:https://github.com/abmcar/ACM/tree/master/OpenjudgeNow/Codeforces/Codeforces%20Round%20%23762%20(Div.%203)
A. Square String?
题目大意:给你一个字符串,让你判断这个字符串是不是由两个相同的字符串组成
思路:截取源字符串的一半,拼接成一个新的字符串,跟源字符串判断是否相同
代码:
void work()
{
string oriString;
cin >> oriString;
string newString = oriString.substr(0, oriString.size() / 2);
if (newString + newString == oriString)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
B. Squares and Cubes
题目大意:给你一个在1e9范围内的数,问有多少数小于这个数且是平方数(ii)或者立方数(ii*i)
思路:直接暴力跑i * i和i * i * i,用map判重
代码:
void work()
{
int n;
cin >> n;
M.clear();
for (int i = 1; i * i <= n; i++)
M[i * i] = 1;
for (int i = 1; i * i * i <= n; i++)
M[i * i * i] = 1;
cout << M.size() << endl;
}
C. Wrong Addition
题目大意:这个麻瓜算竖式不会进位,给你s和a,让你求b使得a+b=s在他错误的进位下成立
思路:已知a长度小于s,且根据题意a/b中的一位相加至多是s的2位,我们知道在他的计算下,多出来的s多出来的位数必定是a的某一位和b的某一位相加进位了,直接dfs判断是否进位,p1,p2,nowAns分别表示s当初位,a当前位,当前的b
代码:
int getSNum(int pos)
{
return (s[pos + 1] - '0') * 10 + s[pos] - '0';
}
void dfs(int p1, int p2, string nowAns)
{
if (p1 == s.size())
{
if (p2 >= a.size())
b = nowAns;
// cout << nowAns << endl;
}
if (p1 >= s.size())
return;
if (p1 < s.size() - 1 && s[p1 + 1] != '0')
{
int oriNum = getSNum(p1);
int nowNum = p2 < a.size() ? a[p2] - '0' : 0;
if (oriNum - nowNum >= 0 && oriNum - nowNum < 10)
dfs(p1 + 2, p2 + 1, nowAns + (char)(oriNum - nowNum + '0'));
}
int oriNum = s[p1] - '0';
int nowNum = p2 < a.size() ? a[p2] - '0' : 0;
if (oriNum - nowNum >= 0 && oriNum - nowNum < 10)
dfs(p1 + 1, p2 + 1, nowAns + (char)(oriNum - nowNum + '0'));
}
void work()
{
cin >> a >> s;
reverse(a.begin(), a.end());
reverse(s.begin(), s.end());
b = "-1";
dfs(0, 0, "");
reverse(b.begin(), b.end());
while (b[0] == '0' && b.size() > 0)
b.erase(0, 1);
if (b == "1-")
b = "-1";
cout << b << endl;
}
D. New Year’s Problem
题目大意:给你一个m*n的数组p,你需要在(n-1)列中找n个不同行的数,使得最小值最大
思路:我们想要找的n个数有2个条件
1.只能在(n-1)列中
2.只能在不同行
分开来看,我们现在思考第一个条件,如果只是这样,可以假设最坏情况,m=n,此时最小值为各列第二大的数中最大的(每列选最大的,有一列选了2个),对于第二个条件,则最小值为每行中最大的数中最小的.
把两个条件结合起来,得到答案–每列次大中最大的和每行最大中较小的
(绕的一b建议好好想一下)
代码:
void work()
{
ans = 0;
cin >> m >> n;
for (int i = 1; i <= n; i++)
p[i].resize(m + 1), p[i].clear();
for (int i = 1; i <= m; i++)
q[i].resize(n + 1), q[i].clear();
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
{
cin >> q[i][j];
p[j][i] = q[i][j];
}
for (int i = 1; i <= m; i++)
sort(q[i].begin() + 1, q[i].begin() + 1 + n, greater<int>());
for (int i = 1; i <= n; i++)
sort(p[i].begin() + 1, p[i].begin() + 1 + m, greater<int>());
for (int i = 1; i <= m; i++)
{
ans = max(ans, q[i][2]);
// cout << q[i][1] << " ";
}
// cout << endl;
for (int i = 1; i <= n; i++)
ans = min(ans, p[i][1]);
cout << ans << endl;
}
E. MEX and Increments
题目大意:给你一个数组,你可以对任意数+1,问能不能使得MEX = 0,1,2,3,…,n,能则求最小操作数
思路:
得到MEX = i的前提是,数组中存在0-(i-1)且不存在i,分开来看,我们用ans表示组成0-(i-1)的操作数,若存在i,则数组中i的数量即为移开i的操作数,我们可以优先队列表示之前的数,cnt表示构成0-(i-1)的代价,每次求MEX = i,把数组中值等于i的数入队,并用当前剩余的数中最大是数加到i,结束,若不剩余,则不可使得Mex = i
代码:
void work()
{
cin >> n;
unordered_map<int, int> M;
vector<int> V(n + 1);
for (int i = 1; i <= n; i++)
cin >> V[i], M[V[i]]++;
priority_queue<int> Q;
vector<int> ans(n + 1, -1);
int cnt = 0;
for (int i = 0; i <= n; i++)
{
ans[i] = cnt + M[i];
while (M[i]--)
Q.push(i);
if (!Q.empty())
{
cnt += i - Q.top();
Q.pop();
}
else
break;
}
for (int i = 0; i <= n; i++)
cout << ans[i] << " ";
}