A:
传送门
思路:数据范围比较小,直接存结果就好了
代码
#include <bits/stdc++.h>
using namespace std;
vector<int> q;
void first()
{
for (int i = 1; i < 10000; i++)
{
if (i % 3 == 0)
continue;
if (i % 10 == 3)
continue;
q.push_back(i);
}
}
int t, n;
int main()
{
first();
cin >> t;
while (t--)
{
cin >> n;
cout << q[n - 1] << endl;
}
return 0;
}
B:
传送门
思路:场上写的代码有点乱,经过学长指点,发现通过a和b可以求出这个圆的一半,进而求出圆的范围,只要a,b,c三个都在范围内一定是有解的
代码
#include <bits/stdc++.h>
using namespace std;
int t;
int a, b, c;
int cir;
bool check()
{
if (a > cir | b > cir || c > cir)
return false;
return true;
}
int main()
{
cin >> t;
while (t--)
{
cin >> a >> b >> c;
cir = abs(a - b) * 2;
if (check())
cout << (c - 1 + cir / 2) % cir + 1 << endl;
else
cout << -1 << endl;
}
return 0;
}
C:
传送门
思路:可以发现,第一列的值分别为i*i,如果将对应的数列和横排看做一个整体,那么这个整体的范围就是 i * i - (2 * (i-1))到 i * i ,然后找到n所在的整体后在进行一下判断就好
代码:
#include <bits/stdc++.h>
using namespace std;
int check(int x)
{
for (int i = 1; i <= 5e4 + 10; i++)
if (x <= i * i && x >= i * i - 2 * (i - 1))
return i;
}
void solve(int x)
{
int l = check(x);
if (x >= l * l - (l - 1))
cout << l << " " << l * l - x + 1 << endl;
else
cout << x - (l * l - 2 * (l - 1)) + 1 << " " << l << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
int x;
cin >> x;
solve(x);
}
return 0;
}
D:
传送门
思路:重点就是只能在字符串的后边添加
考虑由任意字符串P变为某字符串T的步骤:考虑p中哪些字符是不需要删除的,如果某个字符可以在p和t中相对匹配上就不需要删除,比如1052要变乘1024的话,102是可以保留的,如果是1052变1204,那么最多保留12,考虑吧需要增加哪些字符,p中保留下了一部分字符,那么p想变为t,只需要将t中剩余的字符加入末尾即可
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
set<string> q;
int t;
string s;
void init()
{
ll a = 1;
q.insert(to_string(a));
for (int i = 0; i < 63; i++)
{
a *= 2;
q.insert(to_string(a));
}
}
int solve(string s)
{
int ans = 64;
for (auto t : q)
{
int l = 0;
int cnt = 0;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == t[l])
{
l++;
cnt++;
}
if (l >= t.size())
break;
}
ans = min(ans, (int)s.size() - cnt + (int)t.size() - cnt);
}
return ans;
}
int main()
{
init();
cin >> t;
while (t--)
{
cin >> s;
cout << solve(s) << endl;
}
return 0;
}
E:
传送门
思路:首先说一下题意,有一个字符串t和字符串s,每次进行的操作是把s拼接到t的后边,然后删掉b中的某一个字符(把b里边的这个字符全部删除),输入的是最终拼接的t,要求得到一开始的s和删除字符的顺序
首先要明白,留到最后的字符,一定是最后删除的,所以先倒着遍历一次,求出删除的顺序
对字符串中出现的字符进行计数,那么第i个删除的字符,在前i轮拼接的时候,每一轮都会对最终的字符串的长度进行同样的贡献,我们可以求出每个字符每一轮的贡献:数量/被删除的位次,如果不可以整除直接输出-1
然后完整的s是一个字符都没有删除的,然后模拟一遍删除的过程,判断得到的字符串是否与结果相同即可
代码:
#include <bits/stdc++.h>
using namespace std;
int t;
map<char, int> cnt;
int ti[27];
set<char> p;
string s;
int main()
{
cin >> t;
while (t--)
{
cin >> s;
p.clear();
cnt.clear();
memset(ti, 0, sizeof(ti));
string s2 = "";
for (int i = s.size() - 1; i >= 0; i--)
{
if (!p.count(s[i]))
{
s2 += s[i];
p.insert(s[i]);
}
cnt[s[i]]++;
}
reverse(s2.begin(), s2.end());
bool flag = true;
int tot = 0;
for (int i = 0; i < s2.size(); i++)
{
if (cnt[s2[i]] % (i + 1))
{
flag = false;
break;
}
ti[s2[i] - 'a'] = cnt[s2[i]] / (i + 1);
tot += ti[s2[i] - 'a'];
}
if (!flag)
{
cout << -1 << endl;
continue;
}
else
{
int pos = 0;
string s3 = "", s4 = "";
for (int j = 0; j < tot; j++)
s3 += s[j];
s4 += s3;
for (int i = 0; i < s2.size(); i++)
{
string s5 = "";
for (int j = 0; j < s3.size(); j++)
{
if (s3[j] != s2[i])
s5 += s3[j];
}
s3 = s5;
s4 += s5;
}
if (s4 == s)
cout << s.substr(0, tot) << " " << s2 << endl;
else
cout << -1 << endl;
}
}
return 0;
}