链接:https://codeforces.com/contest/1560
总体评价:区分度不错,比之前的div3要难一些。
A
预处理出前\(1000\)个,直接输出即可。
#include <bits/stdc++.h>
const int N = 100050;
const int INF = 1 << 30;
typedef long long ll;
using namespace std;
int n, x, num, ans[N];
int main() {
cin >> n;
for(int i = 1; num <= 1000; i++) {
if(i % 10 == 3 || i % 3 == 0)
continue;
ans[++num] = i;
}
for(int i = 1; i <= n; i++) {
cin >> x;
cout << ans[x] << endl;
}
return 0;
}
B
简简单单画出前几个的情况可以找到规律,加入一些特判的点即可。
#include <bits/stdc++.h>
const int N = 100050;
const int INF = 1 << 30;
typedef long long ll;
using namespace std;
int t, a, b, c, d;
int main() {
cin >> t;
while(t--) {
cin >> a >> b >> c;
d = abs(a - b);
if(abs(a - b) == 1 || min(a, b) > abs(a - b) || c > 2 * d) {
cout << "-1" << endl;
continue;
}
c <= d ? cout << c + d << endl : cout << c - d << endl;
}
return 0;
}
C
也是找规律题。以左上角的\(1\)为中心,向外画圈,看成{1},{2,3,4},{5,6,7,8,9}......这样分组。
看第\(1\)列,\(1,4,9,....n^2\)。看第一行,\(1,2,5,...,(n-1)^2+1\)。看左上到右下的那条对角线,\(1,3,7,...,n^2-n+1\)。
首先初步判定\(k\)是在第几组(环),\(\sqrt{10^9} < 32000\),时间复杂度是可以接受的。
然后再判断得到\(k\)时是行不变还是列不变,输出即可。
#include <bits/stdc++.h>
const int N = 100050;
const int INF = 1 << 30;
typedef long long ll;
using namespace std;
int t, x, n;
int main() {
cin >> t;
while(t--) {
cin >> x;
for(int i = 1; i <= 32000; i++) {
if(i * i >= x) {
n = i;
break;
}
}
if(x <= n * n - n + 1)
cout << x - (n - 1) * (n - 1) << " " << n << endl;
else
cout << n << " " << n - (x - (n * n - n + 1)) << endl;
}
return 0;
}
D
题意
根据题中的规则进行操作,求将给定数变为一个\(2\)的任意次幂的最少操作数。
思路
看数据范围,可以知道我们最多只需预处理到\(10^{18}\),在这个上限以内符合条件的数在\(60\)个左右,我们是可以接受的。
所以可以进行枚举,找到最小的答案。
答案怎么算?其实就是一个双指针的操作。遇到相同的统计一下\((++cnt)\),一起移动指针,否则只移动题中所给的字符串的指针,直到遍历完其中一个字符串。操作次数也就很好算了,等效为把原字符串中与答案不同的先删掉\(+\)答案有但原字符串没有的。
#include <bits/stdc++.h>
const int N = 100;
const int INF = 1 << 30;
typedef long long ll;
using namespace std;
int k, ans;
ll bin[N];
string s;
int calc(ll x) {
string t = "";
while(x) {
t += (x % 10) + '0';
x /= 10;
}
reverse(t.begin(), t.end());
int cnt = 0, j = 0, l = 0;
while(j < s.length() && l < t.length()){
if(s[j] == t[l]) {
++cnt;
j++;
l++;
}
else j++;
}
return s.length() + t.length() - cnt * 2;
}
int main() {
ios::sync_with_stdio(false);
cin >> k;
bin[0] = 1;
for(int i = 1; i <= 62; i++) bin[i] = bin[i - 1] * 2;
while(k--) {
ans = INF;
cin >> s;
for(int i = 0; i <= 62; i++) ans = min(ans, calc(bin[i]));
cout << ans << endl;
}
return 0;
}
F1
题意
给定数\(x,k(k \in [1,2])\),找到最小的\(y\),使得\(y \leq x\)并且保证\(y\)的十进制表示中最多出现\(k\)种数字。
思路
这题要想分类讨论还是太难了......
若\(k=1\),则可以通过枚举找到答案。
若\(k=2\),我们可以枚举确定答案是由哪两个数字组成,同时按贪心思路构造出较小的答案,进行统计。很难想。
#include <bits/stdc++.h>
using namespace std;
int t, k;
set<char> o;
string s;
string calc(char x) {
string y = "";
for(int i = 0; i < s.length(); i++) y += x;
return y;
}
void solve1() {
for(char i = '0'; i <= '9'; i++) {
string t = calc(i);
if(t > s) {
cout << t << endl;
return ;
}
}
}
void solve2() {
string t = calc('9');
for(char i = '0'; i <= '9'; i++) {
for(char j = i + 1; j <= '9'; j++) {
for(int l = 0; l < s.length(); l++) {
if(s[l] < j) {
string g = s;
g[l] < i ? g[l] = i : g[l] = j;
for(int p = l + 1; p < g.length(); p++) g[p] = i;
if(t > g) t = g;
}
if(s[l] != i && s[l] != j) break;
}
}
}
cout << t << endl;
}
int main() {
ios::sync_with_stdio(false);
cin >> t;
while(t--) {
o.clear();
cin >> s >> k;
for(int i = 0; i < s.length(); i++) o.insert(s[i]);
if(o.size() <= k) {
cout << s << endl;
continue;
}
k == 1 ? solve1() : solve2();
}
return 0;
}
还有个超时的做法,就是\(k=2\)时用\(dfs\)来做,也贴在这里吧......
#include <bits/stdc++.h>
using namespace std;
int t, k;
set<char> o;
string s;
string calc(char x) {
string y = "";
for(int i = 0; i < s.length(); i++) y += x;
return y;
}
void solve1() {
for(char i = '0'; i <= '9'; i++) {
string t = calc(i);
if(t > s) {
cout << t << endl;
return ;
}
}
}
void dfs(int step, char t1, char t2, string &t, string p) {
//cout << t << " " << p << endl;
if(step == 2 && p == "0")
return ;
if(step != 1 && p[0] < s[0])
return ;
if(step == s.length() + 1) {
if(p < t && p > s) {
t = p;
return ;
}
return ;
}
string last = p;
dfs(step + 1, t1, t2, t, p + t1);
p = last;
dfs(step + 1, t1, t2, t, p + t2);
p = last;
}
void solve2() {
string t = "", p = "";
t = calc('9');
for(char i = '0'; i <= '9'; i++) {
for(char j = '0'; j <= '9'; j++) {
if(i == j)
continue;
// cout << *it1 << " " << *it2 << endl;
dfs(1, i, j, t, p);
}
}
cout << t << endl;
}
int main() {
ios::sync_with_stdio(false);
cin >> t;
while(t--) {
o.clear();
cin >> s >> k;
for(int i = 0; i < s.length(); i++) o.insert(s[i]);
if(o.size() <= k) {
cout << s << endl;
continue;
}
k == 1 ? solve1() : solve2();
}
return 0;
}