Atcoder HHKB Programming Contest 2020 ABCDE题

题目链接

A题

题意

给定两个字符S,T,如果S为'Y',则把T大写输出;如果S为'N',则小写输出

代码

/*************************************************************************
	> File Name: 1.cpp
	> Author: Knowledge_llz
	> Mail: 925538513@qq.com 
	> Blog: https://blog.csdn.net/Pig_cfbsl 
	> Created Time: 2020/10/10 19:58:30
 ************************************************************************/
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define pb push_back
#define pr pair<int,int>
#define fi first
#define se second
#define LL long long
using namespace std;
int read(){
	char x=getchar(); int u=0,fg=0;
	while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
	while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
	return fg?-u:u;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	freopen("output.out", "w", stdout);
#endif
	char s,t;
	cin>>s>>t;
	if(s=='Y') t=t-'a'+'A';
	cout<<t<<endl;
	return 0;
}

B题

题意

题解

暴力枚举地图上每个'.'的下方和右方是不是'.',并统计答案,\(O(N^2)\)

代码

/*************************************************************************
	> File Name: 1.cpp
	> Author: Knowledge_llz
	> Mail: 925538513@qq.com 
	> Blog: https://blog.csdn.net/Pig_cfbsl 
	> Created Time: 2020/10/10 20:03:44
 ************************************************************************/
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define pb push_back
#define pr pair<int,int>
#define fi first
#define se second
#define LL long long
using namespace std;
int read(){
	char x=getchar(); int u=0,fg=0;
	while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
	while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
	return fg?-u:u;
}
int n,m,ans=0;
char s[250][250];
int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	freopen("output.out", "w", stdout);
#endif
	n=read(); m=read();
	For(i,1,n) scanf("%s",s[i]+1);
	For(i,1,n) For(j,1,m){
		if(s[i][j]=='.'){
			if(s[i+1][j]=='.') ++ans;
			if(s[i][j+1]=='.') ++ans;
		}
	}
	printf("%d\n",ans);
	return 0;
}

C题

题解

因为数的范围限制在了200000以内,每次添加一个数,将该数打上标记,用一个ans指针扫描,如果ans指针指向的数已打上标记则++ans,直到指向一个无标记的数,因为随着序列的增长,ans是递增的,所以ans指针最多扫描200000次,时间复杂度\(O(N)\)

代码

/*************************************************************************
	> File Name: 1.cpp
	> Author: Knowledge_llz
	> Mail: 925538513@qq.com 
	> Blog: https://blog.csdn.net/Pig_cfbsl 
	> Created Time: 2020/10/10 20:03:44
 ************************************************************************/
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define pb push_back
#define pr pair<int,int>
#define fi first
#define se second
#define LL long long
using namespace std;
int read(){
	char x=getchar(); int u=0,fg=0;
	while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
	while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
	return fg?-u:u;
}
const int maxx=2e5+10;
int n,a[maxx],ans=0;
int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	freopen("output.out", "w", stdout);
#endif
	n=read();
	For(i,1,n){
		int u=read();
		++a[u];
		while(a[ans]>0) ++ans;
		printf("%d\n",ans);
	}
	return 0;
}

D题

题意

题解

这个题虽然在D题但其实比E题还难上很多。我也是看了一个日本人的博客翻译了半天才明白。
题意简单说就是在N*N的正方形区域内放置一个A*A和一个B*B的正方形,放置要求不能重叠且四个角要是整数点。
因为是在二维平面内放点,考虑起来比较复杂,我们可以把它投影到一维上。对于两个重叠的正方形投影到XY轴一定有X、Y轴的两根投影线段都会重叠,再看反面,如果有一个轴上的投影没有重叠则正方形一定是没重叠的。所以我们分下面两种情况统计答案:

  1. X轴上两线段不重合,Y轴投影随意放

因为线段都有两头,为简单起见我们只考虑两线段的左端点安放,对于A而言左端点坐标可以为[0,n-a],对于B而言左端点坐标为[0,n-b]
考虑到两线段的左右关系较为麻烦,我们不妨假设B线段一定在A线段的右边。
如果A左端点放置0,B可以放置[a,n-b],共n-b-a+1种放法
如果A左端点放置1,B可以放置[a+1,n-b],共n-b-a种放法
...
如果A左端点放置n-a-b,B可以放置在[n-b,n-b],共1种放法
我们记\(d=(n-a-b)\),于是放法总数有\((d+1)+(d)+(d-1)+...+1=\frac{(d+1)(d+2)}{2}\)
但是这只考虑了B在A右边的情况,B如果在A左边是相同情况,所以X轴上两线段不重合有\((d+1)(d+2)\)种放置方式
Y轴因为是随意放置,利用乘法原理有\((n-a+1)(n-b+1)\)种放法
故总放置方式数为\((d+1)(d+2)(n-a+1)(n-b+1)\)

  1. X轴上两线段重合,Y轴投影不重合

第一种情况已经讨论了X轴上AB不重合的方案数为\((d+1)(d+2)\),而总放法数为\((n-a+1)(n-b+1)\),故重合的方案数为\((n-a+1)(n-b+1)-(d+1)(d+2)\)
而Y轴投影不重合的情况同X轴投影不重合相同,方案数为\((d+1)(d+2)\)
故总放置方式数为\((d+1)(d+2)[(n-a+1)(n-b+1)-(d+1)(d+2)]\)

综上,答案可用表达式\((d+1)(d+2)(n-a+1)(n-b+1)+(d+1)(d+2)[(n-a+1)(n-b+1)-(d+1)(d+2)]\)表示,化简结果为

\[ans=2(d+1)(d+2)(n-a+1)(n-b+1)-[(d+1)(d+2)]^2 \]

当然以上讨论都是建立在N*N的正方形区域是能放下两个正方形的,如果\(N<A+B\)说明放不下要直接输出0。

代码

/*************************************************************************
	> File Name: 1.cpp
	> Author: Knowledge_llz
	> Mail: 925538513@qq.com 
	> Blog: https://blog.csdn.net/Pig_cfbsl 
	> Created Time: 2020/10/11 14:09:05
 ************************************************************************/
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define pb push_back
#define pr pair<int,int>
#define fi first
#define se second
#define LL long long
using namespace std;
int read(){
	char x=getchar(); int u=0,fg=0;
	while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
	while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
	return fg?-u:u;
}
const int mod=1e9+7;
int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	freopen("output.out", "w", stdout);
#endif
	int T=read();
while(T--){
	LL n=read(),a=read(),b=read(),d=n-a-b;
	if(n<a+b){ puts("0"); continue; }
	d=(d+1)*(d+2)%mod;
	a=n-a+1; b=n-b+1;
	n=a*b%mod;
	LL ans=2*d*n%mod-d*d%mod;
	cout<<(ans+mod)%mod<<endl;
}
	return 0;
}

E题

题意

题解

定义k为'.'的个数
因为有\(2^k\)种放置台灯的方案,直接计算每种方案的贡献是不现实的
那么可以考虑对于每个点'.'对答案的贡献,假设当前点A为'.',一共有cnt个'.'放置台灯可以照亮A点,我们想在这\(2^k\)种放置中有多少种方式A点能产生1点贡献,显然只要这cnt个点有一个点放置台灯,那么A点就会产生贡献,而除了这cnt个点其他点都放不放置对A点产生贡献相互独立。于是让A点产生贡献的方式有\((2^{cnt}-1)2^{k-cnt}\)
我们扫描每个点,统计出cnt就能在\(O(\log k)\)的时间复杂度内算出对答案贡献,剩下的问题就是如何统计cnt左侧的'.'。
这时我们可以预处理出所有点往上、下、左、右有多少连续的'.',以左为例:l[x][y]表示(x,y)

  1. 如果当前点不为'.',l[x][y]=0;
  2. 否则, 如果该点左侧为'.',l[x][y]=l[x-1][y]+1

代码

/*************************************************************************
	> File Name: 1.cpp
	> Author: Knowledge_llz
	> Mail: 925538513@qq.com 
	> Blog: https://blog.csdn.net/Pig_cfbsl 
	> Created Time: 2020/10/10 20:03:44
 ************************************************************************/
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define pb push_back
#define pr pair<int,int>
#define fi first
#define se second
#define LL long long
using namespace std;
int read(){
	char x=getchar(); int u=0,fg=0;
	while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
	while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
	return fg?-u:u;
}
const int mod=1e9+7;
int n,m,dx[5]={0,0,-1,1},dy[5]={-1,1,0,0};
LL ans=0,num=0,l[2020][2020],r[2020][2020],u[2020][2020],d[2020][2020];
char s[2020][2020];
LL qpow(LL y){
	LL x=2,res=1;
	while(y){
		if(y&1) res=(res*x)%mod;
		x=x*x%mod;
		y>>=1;
	}
	return res;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	freopen("output.out", "w", stdout);
#endif
	n=read(); m=read();
	For(i,1,n) scanf("%s",s[i]+1);
	For(i,1,n) For(j,1,m){
		num+=(s[i][j]=='.');
		if(s[i][j]=='.'){
			if(s[i-1][j]=='.') u[i][j]=u[i-1][j]+1;
			if(s[i][j-1]=='.') l[i][j]=l[i][j-1]+1;
		}
	}
	for(int i=n;i;--i) for(int j=m;j;--j)
		if(s[i][j]=='.'){
			if(s[i+1][j]=='.') d[i][j]=d[i+1][j]+1;
			if(s[i][j+1]=='.') r[i][j]=r[i][j+1]+1;
		}
	For(i,1,n) For(j,1,m)
		if(s[i][j]=='.'){
			LL tmp=1+l[i][j]+r[i][j]+u[i][j]+d[i][j];
			ans+=(qpow(tmp)-1ll)*qpow(num-tmp)%mod;
			ans%=mod;
		}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2020-10-11 21:14  Knowledge-Pig  阅读(244)  评论(0编辑  收藏  举报