CF739 A-E

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值