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)
待补