Codeforces Round #739 (Div. 3)

Codeforces Round #739 (Div. 3)

比赛链接:https://codeforces.com/contest/1560

A. Dislike of Threes

题目大意:找出Polycarp写下的数中的第k个数(3的倍数和数位有3的将不会被写下,如:3、6、9、12、13等)。
分析:见代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 5010;
int a[N];
int k,cnt;
bool check(int i)
{
    if(i%3==0) return false;
        int t=i%10;
        if(t==3) return false;
    return true;
}

int main()
{
    int T;
    scanf("%d", &T);
    for(int i=1;i<=5000;i++)
        if(check(i)) a[++cnt]=i; //在a中存下Polycarp所写下的数
    while(T--)
    {
        scanf("%d", &k);
        printf("%d\n",a[k]);
    }
    return 0;
}

B. Who’s Opposite?

题目大意:由一段连续的自然数组成的圈子,其中a对应b,让你求出c对应的数,如果不存在圈子或不存在c对应的数,则输出 “ -1 ”。
分析:不难看出,圈子中每个数字和自己对应的的差值都是n/2,那么将差值乘以2得到的就是圈子的最大数,超过这个数代表不存在对应的数或圈子。

#include<iostream>
using namespace std;
int main(){
	int T;
	cin>>T;
	while(T--){
		int a,b,c;
		cin>>a>>b>>c;
		int n=abs(a-b)*2;
		if(a>n||b>n||c>n)cout<<"-1"<<endl; 
		else {
			if(c>n/2)cout<<c-n/2<<endl; //根据c与中间值大小比较来求对应的数
			else cout<<c+n/2<<endl;
		}
	}
	return 0;
}

C. Infinity Table

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
typedef long long LL;

int k;
int cnt1,cnt2;
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        
        scanf("%d", &k);
        for (int i = 1; i <= 40000; i ++ )
            if(k<=(LL)i*i){ //找到最小的大于等于k的值
                cnt1=i*i; //代表该外围直角的最大值
                cnt2=i;  
                break;
            }
        int flag=cnt1-cnt2+1; //代表该外围直角对角线上的数
        if(k==flag) printf("%d %d\n",cnt2,cnt2); //是的话直接输出
        else if(k<flag) printf("%d %d\n",cnt2-(flag-k),cnt2); //代表k在第i列
        else printf("%d %d\n",cnt2,cnt1-k+1); //代表k在第i行
    }
    return 0;
}

D. Make a Power of Two

因为1<=n<=109,所有我们只用考虑1到1018范围内的2的整数次幂,只有60个。所以我们只要计算n转换成每个2的整数次幂所需的操作次数,再取个最小值就可以了。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;
const int N = 110;

string n;
string s[100];

int check(string a,string b)
{
    int lena=a.size(),lenb=b.size();
    int i=0,j=0;
    while(i<lena && j<lenb)
    {
        if(a[i]==b[j]) i++,j++;
        else i++;
    }
    //a中能留下的字符数量就是a中子序列与b前缀匹配的最大长度,即j
    return lena-j+lenb-j;
}

int main()
{
	int T;
	cin>>T;
	LL num=1;
	for(int i=0;i<=60;i++)
	   s[i]=to_string(num<<i); //to_string()函数将数字转换成字符串
	while(T--)
	{
	    cin>>n;
	    int res=100; 
	    for(int i = 0; i <= 60; i ++ )
	       res=min(res,check(n,s[i]));
	       
	    cout<<res<<endl;
	}
    return 0;
}

E. Polycarp and String Transformation

思路
1.将最终串由后往前遍历,得出字母删除的逆序,并记录每个字母在最终串中出现的次数。
2.将逆序翻转,即得到删除字母的顺序,遍历该顺序,因为字母在最终串中出现的次数一定是它的删除次序的倍数(即在第几次被删除),所以我们通过是否是倍数来判断是否合法。如果不合法就跳出,并输出"-1",后面的操作就都不用进行了,否则用cnt加上每个字母在最终串中出现的次数除以它的删除次序(即它在原串中的出现次数),最终cnt即为原串的长度。
3.在第二步我们得到了原串的长度,所以我们直接截取最终串的前cnt个字符,就得到了原串。然而还没有完,我们还需要判断得到的原串是否是合法的,可以对我们得到的原串按前面得到的删除字母的顺序依次删除字母,若最后得到的字符串和最终串是相同的,那该原串就是合法的,我们就输出它和删除顺序,否则输出 -1

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        string final_s,order_s; //最终串,删除字母的顺序
        cin>>final_s;
        int n=final_s.size(); //求最终串的长度
        map<char,int> num,st; //用map来存字母出现次数
        for(int i=n-1;i>=0;i--)
        {
            if(!num[final_s[i]]) order_s+=final_s[i]; 
            //如果该字母没出现过,加入删除逆序
            num[final_s[i]]++; //记录字母出现次数
        }
        int cnt=0; //原串的长度
        bool flag=false;
        reverse(order_s.begin(),order_s.end()); //翻转删除逆序得到删除顺序
        for(int i=0;i<order_s.size();i++)
           if(num[order_s[i]]%(i+1))
           {
               flag=true;
               break;
           }
           else cnt+=num[order_s[i]]/(i+1);
        
        if(flag)
        {
            puts("-1");
            continue;
        }
        
        string origin_s=final_s.substr(0,cnt); //截取得到原串
        string check_s=origin_s; 
        //check_s用于检查原串是否合法,先加上未删除一个字母(即原串)的时候
        for(int i=0;i<order_s.size();i++)
        {
            st[order_s[i]]=1; //标记一下,表示该字母已被删除
            for(int j=0;j<origin_s.size();j++)
               if(!st[origin_s[j]]) check_s+=origin_s[j];
               //将未被删除的字母一个个到检查串中
        }
        //最后得到的检查串应与最终串相同
        if(check_s!=final_s) puts("-1");
        else cout<<origin_s<<' '<<order_s<<endl;
    }
    return 0;
}

F1. Nearest Beautiful Number (easy version)

待补

F2. Nearest Beautiful Number (hard version)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值