Codeforces Round #587 (Div. 3) 比赛&补题
1216A. Prefixes
题意
给一个字符串,长度为偶数,只包含小写字母a和b,你可以变换其中任意一个字母,把a换成b或者把b换成a。要求最后结果中的字符串任意偶数前缀a和b的数量相同。
题解
只需要保证第i个字母和第i+1个字母不相同就行了,i每次递增2。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 31;
int main()
{
string s;
int n, ans=0;
cin >>n >>s;
for(int i=0; i<n-1; i+=2)
{
if(s[i]==s[i+1])
{
if(s[i]=='a')
s[i] = 'b';
else
s[i] = 'a';
ans++;
}
}
cout <<ans <<endl;
cout <<s <<endl;
return 0;
}
1216B. Shooting
题意
给你几个罐子,每个罐子的耐久度为ai,你要将所有罐子击碎,当你要击碎第i个罐子时,你需要射击(ai*x+1)次,其中x为你已经击碎的罐子,可认为你将一个罐子击碎才会去射击下一个罐子。
题解
x是重点,只要反向排一下序就行了,有些类似哈夫曼树。一开始以为最后让依次输出第i个罐子是第几次被射击的,后来WA了一次才发现是让依次输出射击的是第几个罐子。。。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000+10;
struct A
{
int ai, index;
}ax[maxn];
bool cmp1(A a, A b)
{
return a.ai>b.ai;
}
int main()
{
int n;
cin >>n;
for(int i=0; i<n; i++)
{
cin >>ax[i].ai;
ax[i].index = i+1;
}
int x=0, ans=0;
sort(ax, ax+n, cmp1);
for(int i=0; i<n; i++)
{
ans+=(ax[i].ai*x+1);
x++;
}
cout <<ans <<endl;
cout <<ax[0].index;
for(int i=1; i<n; i++)
cout <<' ' <<ax[i].index;
cout <<endl;
return 0;
}
1216C. White Sheet
题意
给你一个白纸的左下角和右上角坐标,还有两张黑纸的左下角和右上角坐标,保证这三张纸的边缘都平行于坐标轴,问你黑纸是否能完全覆盖住白纸。
题解
坐标范围1e6,可以依次遍历白纸边缘的每一个点,看他是否在黑纸内,递增要设成0.5,不能设成1,最后没时间了,不知道思路对不对,回来再来补吧。(补:果然过了,太智障了。。。)
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int main()
{
int x1, y1, x2, y2;
int x3, y3, x4, y4;
int x5, y5, x6, y6;
cin >>x1 >>y1 >>x2 >>y2;
cin >>x3 >>y3 >>x4 >>y4;
cin >>x5 >>y5 >>x6 >>y6;
for(double i=x1; i<=x2; i+=0.5)
{
if((i<=x4&&i>=x3&&y1<=y4&&y1>=y3) || (i<=x6&&i>=x5&&y1<=y6&&y1>=y5))
continue;
else
{
cout <<"YES" <<endl;
return 0;
}
}
for(double i=y1; i<=y2; i+=0.5)
{
if((i<=y4&&i>=y3&&x1<=x4&&x1>=x3) || (i<=y6&&i>=y5&&x1<=x6&&x1>=x5))
continue;
else
{
cout <<"YES" <<endl;
return 0;
}
}
for(double i=x2; i>=x1; i-=0.5)
{
if((i<=x4&&i>=x3&&y2<=y4&&y2>=y3) || (i<=x6&&i>=x5&&y2<=y6&&y2>=y5))
continue;
else
{
cout <<"YES" <<endl;
return 0;
}
}
for(double i=y2; i>=y2; i-=0.5)
{
if((i<=y4&&i>=y3&&x2<=x4&&x2>=x3) || (i<=y6&&i>=y5&&x2<=x6&&x2>=x5))
continue;
else
{
cout <<"YES" <<endl;
return 0;
}
}
cout <<"NO" <<endl;
return 0;
}
1216D. Swords
题意
地下室有n种剑,每种剑有x个,有y个人来地下室偷剑,每个人只拿一种剑,每个人拿了z个剑。现在发现地下室的剑被偷了,每种剑剩下ai个,其中x, y, z未知,给出n和ai,让你求出最少y个人来偷剑和每个人偷了多少剑z。
题解
用最大的数依次减去其他所有ai,求他们所有的最大公因数,然后再用前面算出来的最大数和其他数的差除以最大公因数,则可算出有多少人来偷剑了,最大公因数即为每个人偷了多少剑。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int a[maxn];
stack<int> s, ss;
bool cmp(int x, int y)
{
return x>y;
}
int main()
{
int n;
scanf("%d", &n);
for(int i=0; i<n; i++)
scanf("%d", &a[i]);
sort(a, a+n, cmp);
int x, y;
for(int i=1; i<n; i++)
{
x = a[0]-a[i];
if(x)
{
s.push(x);
ss.push(x);
}
}
while(s.size()>1)
{
x = s.top();
s.pop();
y = s.top();
s.pop();
s.push(__gcd(x, y));
}
ll ans=0;
while(!ss.empty())
{
x = ss.top();
ss.pop();
ans+=(x/s.top());
}
printf("%lld %d\n", ans, s.top());
return 0;
}
1216E1. Numerical Sequence (easy version)
题意
11212312341234512345612345671234567812345678912345678910......,给你一个这样的无限循环数列,1、12、123、1234、12345......这样循环,询问q次,每次询问在这个数列中第k位是什么数字。注意:11算两位数字,而不是一个数字。k最大为1e9,q不大于100。
题解

由程序算出当k为1e9时总共也才21837个数,所以我们只用预处理出前1e5个数的排列,预处理时记录下每个数的最后一位排到哪里了,最后直接查表就行了。
计算程序:
ll k=0, i=1, x;
while(k<=1000000000){
for(ll j=1; j<=i; j++){
x = j;
while(x){k++;x/=10;}
}
i++;
}
代码
#include <iostream>
#include <queue>
#include <string.h>
#define ll long long
using namespace std;
const int maxn = 1e5+10;
int num[maxn*5], pre[maxn], n;
inline void cal(int x)
{
if(!x)
return;
cal(x/10);
num[++n] = x%10;
return;
}
int main()
{
int x;
n = 0;
for(int i=1; i<=100000; i++)
{
cal(i);
pre[i] = n;
}
int q;
ll k;
cin >>q;
while(q--)
{
cin >>k;
ll sum=0;
for(int i=1; i<100000; i++)
{
if(sum+pre[i]<k)
sum+=pre[i];
else
{
cout <<num[k-sum] <<endl;
break;
}
}
}
return 0;
}

浙公网安备 33010602011771号