Codeforces Round 905 (Div. 3)
目录
- A. Morning
- 题意
- 思路
- 核心代码
- B. Chemistry
- 题意
- 思路
- 核心代码
- C. Raspberries
- 题意
- 思路
- 核心代码
- D. In Love
- 题意
- 思路
- 核心代码
- E. Look Back
- 题意
- 思路
- 核心代码
A. Morning
题意
从一开始,每一次操作可以选择当前的数字打印或者是移动到左右相邻的数字,具体排列看上图,给出一个标签四位数,求打印出来的操作次数
思路
求相邻两个数字之间的距离差累加
核心代码
void solve()
{
string s;
cin>>s;
int ans=0;
if(s[0]=='0')s[0]+=10;
ans=abs(s[0]-'1');
for(int i=1;i<4;++i)
{
if(s[i]=='0')s[i]+=10;
ans+=abs(s[i]-s[i-1]);
}
ans+=4;
cout<<ans<<endl;
}
B. Chemistry
题意
给你一个长度为n的字符串以及可以删除的字符个数k,询问删除之后重新排列能否构成回文字符串
思路
要想构成回文字符串所有的字母出现的次数都要是偶数,除了最中间的那一个字母可以是出现奇数次。然后是删除的k次,如果k大于原字符串中出现奇数次数的字母个数,那么后面多余的次数就可以去删除出现偶数次的字母,最后一定能够构成回文字符串,k不够大的话那就不能构成了
核心代码
void solve()
{
int n,k;
scanf("%d%d",&n,&k);
string s;
cin>>s;
int len=s.size();
int arr[26]{};
for(int i=0;i<len;++i)
{
arr[s[i]-'a']++;
}
int geshu=0;
int sum=0;
for(int i=0;i<26;++i)
{
if(arr[i]&1)geshu++;
sum+=arr[i];
}
if(geshu<=k+1)printf("YES\n");
else printf("NO\n");
}
C. Raspberries
题意
给你一组长度为n的数组,以及一个整数k,每一次可以对数组里面的任意一个数字进行加一操作,问最少执行多少次可以使得这个数组里面所有的数字的乘积是k的倍数
思路
如果k是质数,那么我们只需要满足这个数组里面有一个数字是k的倍数就可以了,可以对每一个数字进行枚举找最小的那一个,但是如果是合数怎么操作呢,本题只有一个合数4,单独进行特判就可以了
核心代码
void solve()
{
int n,k;
scanf("%d%d",&n,&k);
int minzhi=INT_MAX;
int input;
int oushu=0;
int jishu=0;
for(int i=0;i<n;++i)
{
scanf("%d",&input);
if(input&1)jishu++;
else oushu++;
if(input%k==0)minzhi=0;
else minzhi=min(minzhi,k-input%k);
}
if(k!=4)
{
printf("%d\n",minzhi);
return ;
}
if(oushu>=2)printf("0\n");
else if(oushu==1&&jishu>=1)printf("%d\n",min(minzhi,1));
else if(oushu==1&&jishu==0)printf("%d\n",min(minzhi,2));
else if(oushu==0&&jishu>=2)printf("%d\n",min(minzhi,2));
return ;
}
D. In Love
题意
每一次增加一个边或者减少一个边,操作完之后询问是否存在一对不重合的边
思路
如果存在一对不重合的边,那么必然存在一条边的右端点小于一条边的左端点,我们只需要看最小的右端点是否小于最大的左端点即可
核心代码
void solve()
{
int n;
cin>>n;
multiset<int>l,r;
for(int i=0;i<n;++i)
{
char a;
int x,y;
cin>>a>>x>>y;
if(a=='+')
{
l.insert(x);
r.insert(y);
}
else
{
l.erase(l.find(x));
r.erase(r.find(y));
}
if(l.size() > 1 && *r.begin() < *l.rbegin())printf("YES\n");
else printf("NO\n");
}
}
E. Look Back
题意
给你一组长度为n的数组,每一次可以选择一个数组乘以2,最少需要多少次可以使得这个数组变成一个非递减数组
思路
只需要从前往后进行贪心枚举就可以了,但是这个题目数据量有点大,不能直接存储每一个数字变化之后的数字,需要转化一下,比如我们可以通过前后两个数字的大小倍数关系来求
核心代码
void solve()
{
int n;
scanf("%d",&n);
long long a=0,b;
long long ans=0;
long long num=0;
long long bei=0;
scanf("%lld",&a);
for(int i=1;i<n;++i)
{
scanf("%lld",&b);
if(b>a)
{
int a2=a;
while(a2<=b&&a2!=0)
{
a2<<=1;
num--;
}
num++;
num=num>0?num:0;
ans+=num;
a=b;
continue;
}
else if(a==b)
{
ans+=num;
continue;
}
else
{
int b2=b;
while(b2<a)
{
num++;
b2<<=1;
}
ans+=num;
a=b;
}
}
printf("%lld\n",ans);
}