Atcoder abc/365场题解

95 阅读2分钟

视频题解: www.bilibili.com/video/BV1ai…

A - Sanitize Hands (atcoder.jp)

思想

这道题是求最长前缀

前x个前缀和如果大于m了,那么就不再向后累加了,输出此时的前缀即可. image.png

B - Uppercase and Lowercase (atcoder.jp)

思想

第二个题是个签到题,一次过:

#include<bits/stdc++.h>
using namespace std;

int cnt1,cnt2;
int main()
{
	string s;cin>>s;
	
    for(int i=0;i<s.size();i++)
    {
    	if(islower(s[i]))
    	{
    	 cnt1++;
		}
		else cnt2++;
	}
	
	if(cnt1>cnt2) 
	{
		for(int i=0;i<s.size();i++)
		{
			s[i]=tolower(s[i]);
		}
	}
	else
	{
		for(int i=0;i<s.size();i++)
		{
			s[i]=toupper(s[i]);
		}
	}
	
    cout<<s<<endl;
 	return 0;
}

image.png

C - Sierpinski carpet (atcoder.jp)

题意解析

image.png

题目的意思是说 当前等级网格的每一个网格块都是由9个上一等级网格构成的.

例如下图左边是一等级网格,右边是二等级网格. 二等级网格的每一个网格块都是由一等级网格构成的: image.png

二等级网格是由9个一等级网格的网格块组成的,其中八个一等级网格块构成了二等级网格的外围,二等级网格中间部分全部填充为'.'

解题思想

因为N的数据范围很小,所以可以模拟做: image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1000,M=200005;
char s[N][N];
char a[10];
int  n;

void dfs(int u,int x,int y)
{
  	if(u==0) return;
  	int d=a[u-1];
  	for(int i=x+d;i<x+2*d;i++)
  	  for(int j=y+d;j<y+2*d;j++)
  	    s[i][j]='.';
  	    
  	//剩下的八层递归下去 
  	for(int i=0;i<3;i++)
  	{
  	  for(int j=1;j<3;j++)	
	  {
	  	if(i==1&&j==1)continue;
	  	dfs(u-1,x+i*d,y+j*d);	
	  }
	}

}
int main()
{
	cin.tie(nullptr)->sync_with_stdio(0); 
	a[0]=1;
	for(int i=1;i<=6;i++) a[i]=a[i-1]*3;
	
	
	cin>>n; 
	int w=a[n];  //边长 
	
	//先把矩阵全部初始化为'#' 
	for(int i=0;i<w;i++)
	{
		for(int j=0;j<w;j++)
		{
			s[i][j]='#';
		}
	}
	
	dfs(n,0,0); //n表示n层 (0,0)代表左上角 
	for(int i=0;i<w;i++) puts(s[i]); 
	
	
	return 0;
}

D - 88888888 (atcoder.jp)

这道题让我们求n个n拼接 % MOD的结果

但是注意n特别大 image.png

那么首先我们要算出n个n拼接之后的数.拿当n==5时举例,它的拼接方法如下:

image.png

我们可以用公式表示为:

image.png

image.png 我们注意这是一个等比数列,我们可以用等比数列求和公式求出结果: 为了方便计算,我们把公式做了变化:

image.png

然后就可以计算了, 因为:

image.png

把公比10q10^{q},a1=100a1=10^{0}代入,得:

image.png

这样我们就计算出来了x,最后我们1还要对x取模,那么就变为:

image.png

code

分子分母的单独计算都用快速幂去求,分子/分母通过逆元转化为分子*分母的逆元

整体代码如下:

image.png

再单独看看最重要的计算那部分:

image.png

image.png