Atcoder Beginner Contest 174(ABC174) 题解

打到了 R a n k   33 Rank\ 33 Rank 33,还是不错的。

第一次顺顺畅畅没有WA地AK了一场ABC,写篇题解纪念一下……

Solution

T1

直接模拟即可。

T2

分别枚举每个点并用已给的公式算出其与原点的距离,然后统计距离不大于 k k k的点数即可。

建议用 l o n g   d o u b l e long\ double long double存储。

T3

暴力即可,考虑如何快速判断 k k k 1 1 1时其是否能被 n n n整除。

我们可以维护一个值,即当前这么多 1 1 1组成的数模 n n n的值。考虑在末尾加上一个 1 1 1后,原数 x x x变为了 10 x + 1 10x+1 10x+1,那么模数也乘 10 10 10 1 1 1,即模数可以 O ( 1 ) O(1) O(1)维护

当模数为 0 0 0时显然满足要求,立即输出并结束即可。注意当位数达到一定量的时候,应跳出循环输出 − 1 -1 1

T4

显然,满足要求的条件是,左边清一色的 R R R且右边清一色的 W W W

于是,我们算出 W W W的数量为 c n t cnt cnt,在原字符串的最后 c n t cnt cnt位中数出不为 W W W的字符数量,即为答案。

注意,这种做法的正确性在于,在后面 c n t cnt cnt位中,每遇到一个不是 W W W的字符就应当与前面 n − c n t n-cnt ncnt个字符中一个不为 R R R的字符交换,此时满足要求且决策最优。

T5

首先,思考这样一个问题: 如果一个块的长度为 x x x,每次把它劈成两个块,最终要求任何一个块的长度均不超过 l e n len len,求最少劈的次数。

我们可以贪心地操作,即对于长木块,每次都劈掉一块长度为 l e n len len的,直到满足要求,此时决策最优且劈的次数为 ⌈ a b ⌉ − 1 \lceil \frac a b \rceil -1 ba1

回到原题,可以发现是一道有单调性的二分题(最小值最大, 最大值最小这种字眼应该很敏感吧)。我们每次判断: 能否让块的最大值最终不大于 m i d mid mid且劈的次数不多于 k k k次。判断的方式就是判断 ∑ i = 1 n ( ⌈ a i m i d ⌉ − 1 ) \sum_{i=1}^n (\lceil \frac {a_i} {mid} \rceil -1) i=1n(midai1)的值是否超过了 k k k,其中前者表示,分别考虑每个块至少要被劈的次数使得其产生的新块中不含大于 m i d mid mid的块。

时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

T6

P 1972 P1972 P1972撞题,思路详见 P 1972 P1972 P1972

看这里

Code

T1

#include 
#define int long long
using namespace std;

int n;

signed main()
{
	cin>>n;
	if (n>=30)  cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	
	return 0;
}

T2

#include 
#define int long long
#define double long double
using namespace std;

int n,d,ans=0;
double x,y;

signed main()
{
	cin>>n>>d;
	for (int i=1;i<=n;i++)
	{
		cin>>x>>y;
		
		double len=sqrt(x*x+y*y);
		if (len<=d)  ans++;
	}
	cout<<ans<<endl;
	
	return 0;
}

T3

#include 
#define int long long
using namespace std;

int n,ii=0,now=0;

signed main()
{
	cin>>n;
	while (ii<=80000000)
	{
		ii++;
		now=(now*10+7)%n;
		
		if (now==0)  return cout<<ii<<endl,0;
	}
	cout<<-1<<endl;
	return 0;
}

T4

#include 
#define int long long
using namespace std;

int n,cnt=0,ans=0;
char a[200005];

signed main()
{
	cin>>n;
	for (int i=1;i<=n;i++)  cin>>a[i];
	for (int i=1;i<=n;i++)
	{
		if (a[i]=='W')  cnt++;
	}
	for (int i=n-cnt+1;i<=n;i++)
	{
		if (a[i]!='W')  ans++;
	}
	cout<<ans<<endl;
	
	return 0;
}

T5

#include 
#define int long long
using namespace std;

int n,k,ans=1e9+7;
int a[200005];

inline int up(int aa,int bb)
{
	if (aa%bb==0)  return aa/bb;
	else return (aa/bb)+1;
}

bool check(int len)//check函数
{
	int tot=0;
	for (int i=1;i<=n;i++)  tot=tot+up(a[i],len)-1;
	
	if (tot<=k)  return true;
	else return false;
}

int Binary_search(int l,int r)//递归式二分写法
{
	if (l==r||l+1==r)
	{
		if (check(l))  ans=min(ans,l);
		if (check(r))  ans=min(ans,r);
		return ans; 
	}
	int mid=(l+r)>>1;
	if (check(mid))
	{
		ans=min(ans,mid);
		return Binary_search(l,mid);
	}
	else return Binary_search(mid+1,r);
}

signed main()
{
	cin>>n>>k;
	for (int i=1;i<=n;i++)  cin>>a[i];
	
	cout<<Binary_search(1,1e9)<<endl;
	
	return 0;
}

T6

详见原题的题解。

你可能感兴趣的:(比赛题解,算法)