Codeforces Round #739 (Div. 3) A~F2

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!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值