A Dislike of Threes
题目大意
规定是3的倍数或者数的最后一位是3的数是漂亮数,给定一个数n,求第n个不漂亮数是多少
主要思路
由于n的范围是1000,直接打表即可
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 200010;
int n, a[N];
vector<int> s;
bool check(int x)
{
if(x % 3 == 0) return true;
if(x % 10 == 3) return true;
return false;
}
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
for(int i = 1; i <= 10000; i++)
{
if(!check(i)) s.push_back(i);
}
int T;
cin >> T;
while(T--)
{
int x;
cin >> x;
cout << s[x - 1] << endl;
}
return 0;
}
B Who’s Opposite?
题目大意
有一个圆上有均匀分布许多点,给定三个数a,b,c,且在圆中a与b相对,问与c相对的数是几
主要思路
首先a,b相对那么这个圆一定由a,b这条线分为两部分,那么该圆中一共有|a - b| * 2个点,于是如果该圆存在,那么结果一定为c + n / 2 或者 c - n / 2
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int t;
cin >> t;
while (t--)
{
ll a, b, c;
cin >> a >> b >> c;
ll n = 2 * abs(a - b);
if (a > n || b > n || c > n)
cout << -1 << '\n';
else
{
ll d = n / 2 + c;
while (d > n) d -= n;
cout << d << '\n';
}
}
return 0;
}
C Infinity Table
题目大意
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EOQgUvCB-1629368325843)(C:\Users\zhb\AppData\Roaming\Typora\typora-user-images\image-20210819165903243.png)]
问第k个数在哪个点
主要思路
我们先确定该数在第几层,然后确定具体位置即可
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 200010;
int n, a[N];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
cin >> n;
int k = 1;
int num = 1;
while(num < n)
{
k++;
num += 2 * k - 1;
}
//当前在第k层
num -= 2 * k - 1;
int t = n - num;
if(t <= k) cout << t << ' ' << k << endl;
else cout << k << ' ' << k - (t - k) << endl;
}
return 0;
}
D Make a Power of Two
题目大意
给定一个数n,给定两种操作
- 删除任意一个数字
- 在结尾添加一个数字
用最少的操作使n成为2的次幂
主要思路
首先枚举2所有次幂,每次找使得n变为该数最小次数,求所有数的最小值
那么问题变成如何如何将一个数n变为k且步数最小
由于只能从结尾添加 所以我们遍历k,看n能和k匹配j的最大前缀是多少,然后就能确定最小步数了
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 110;
int n, a[N];
int st[N];
vector<int> t1, t2;
int work(int n, int k)
{
//debug(k)
int cnt1 = 0, cnt2 = 0;
int res = 0;
t1.clear();
t2.clear();
while(n)
{
t1.push_back(n % 10);
n /= 10;
}
while(k)
{
t2.push_back(k % 10);
k /= 10;
}
reverse(t1.begin(), t1.end());
reverse(t2.begin(), t2.end());
for(int len = t2.size(); len >= 0; len--)//枚举最长匹配长度
{
int r = len - 1;
bool flag = true;
int i = 0, l = 0;
while(i < t1.size() && l <= r)
{
if(t1[i] == t2[l]) i++, l++;
else
{
i++;
}
}
if(l <= r) flag = false;
if(flag)
{
//debug(len)
return t2.size() - len + t1.size() - len;
}
}
}
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
st[0] = 1;
for(int i = 1; i < 63; i++)
{
st[i] = st[i - 1] * 2;
}
int T;
cin >> T;
while(T--)
{
cin >> n;
int ans = 1e9;
for(int i = 0; i < 63; i++)
{
int t = work(n, st[i]);
if(t < ans)
{
ans = t;
}
}
cout << ans << endl;
}
return 0;
}
E Polycarp and String Transformation
题目大意
给定一个字符串t,问能否通过字符串s进行操作来得到字符串t
刚开始t初始化为s
操作步骤
- 选出一个s中的字符c
- 删除s中所有的字符c
- 将删除字符后的s加到t中
主要思路
观察可知,删除字符的序列一定为每一个字符最后出现的位置进行排列,因为最后删除的一定出现在t串最后
接下来考虑如何得到初始的s,由于如果没删除某个字符那么t中的该字符一定是s中该字符的整数倍
比如第二个删除字符a,那么t中的a数量就是s中的2倍,因此根据t串和被删除的字符串就能求的s,接下来验证s能否得到t即可
AC代码
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
int cnt[30];
int ans[30];
void init()
{
memset(ans, 0, sizeof(ans));
memset(cnt, 0, sizeof(cnt));
}
bool check(string s, string t, string x)
{
string ans = s;
for(int i = 0; i < t.size(); i++)
{
string st;
for(int j = 0; j < s.size(); j++)
{
if(s[j] != t[i]) ans += s[j], st += s[j];
}
s = st;
}
if(x == ans) return true;
else return false;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
init();
string ans1, ans2;
string s;
cin >> s;
for(int i = s.size() - 1; i >= 0; i--)
{
if(!cnt[s[i] - 'a']) ans2 += s[i];
cnt[s[i] - 'a']++;
}
reverse(ans2.begin(), ans2.end());//得到按顺序被删除的字符
bool flag = true;
int num = 0;//存储s中所有字符的数量
for(int i = 0; i < ans2.size(); i++)//ans数组存储s中某个字母的数量
{
if(cnt[ans2[i] - 'a'] % (i + 1) == 0)
{
ans[ans2[i] - 'a'] = cnt[ans2[i] - 'a'] / (i + 1);
num += ans[ans2[i] - 'a'];
}
else flag = false;
}
int pos = 0;
while(num && pos < s.size())
{
if(ans[s[pos] - 'a']) ans[s[pos] - 'a']--, ans1 += s[pos], pos++, num--;
else
{
flag = false;
break;
}
}
if(!check(ans1, ans2, s)) flag = false;
if(flag) cout << ans1 << ' ' << ans2 << endl;
else cout << "-1" << endl;
}
return 0;
}
F Nearest Beautiful Number (easy version)
题目大意
给定两个数n,k,问最小的大于等于n的且最多有k个不同数字的最小数是多少
主要思路
先判断当前n不同数字是否小于等于k,如果是直接输出,如果是则找到第一个大于k的不同数,然后使该位加1,后面全置为0,然后再判断当前n不同数字是否小于等于k,如此反复即可
这样我们找到的第一个符合条件的n就是最小值
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define debug(a) cout << #a << " = " << a << endl;
#define x first
#define y second
typedef long long ll;
const int N = 200010;
int n, a[N];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--)
{
string n;
int k;
cin >> n >> k;
while(true)
{
set<char> s;
for(int i = 0; i < n.size(); i++) s.insert(n[i]);
if(s.size() <= k)
{
cout << n << endl;
break;
}
else
{
s.clear();
int pos = 0;
while(true)
{
s.insert(n[pos]);
if(s.size() > k)
{
while(n[pos] == '9') pos--;
n[pos]++;
for(int i = pos + 1; i < n.size(); i++) n[i] = '0';
break;
}
pos++;
}
}
}
}
return 0;
}
F2 Nearest Beautiful Number (hard version)
同F1!!!