• 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
    ",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
    ",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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    黄聪:基于jQuery+JSON的省市区三级地区联动
    黄聪:jquery 校验中国身份证号码
    黄聪: Bootstrap之Form表单验证神器: BootstrapValidator(转)
    黄聪:MySQL 按指定字段自定义列表排序
    黄聪:MYSQL使服务器内存CPU占用过高问题的分析及解决方法
    黄聪:PHP 防护XSS,SQL,代码执行,文件包含等多种高危漏洞
    黄聪:解决丢失api-ms-win-crt-runtime-|1-1-0.dll的问题:vc_redist.x64
    黄聪:如何开启IIS7以上的“IIS6管理兼容性”
    黄聪:怎么清理win7、win8更新垃圾(winsxs目录清理)
    黄聪:Mysql5.6缓存命中率
  • 原文地址:https://www.cnblogs.com/Knowledge-Pig/p/13799381.html
Copyright © 2020-2023  润新知