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轴的两根投影线段都会重叠,再看反面,如果有一个轴上的投影没有重叠则正方形一定是没重叠的。所以我们分下面两种情况统计答案:
- 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))
- 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)])表示,化简结果为
当然以上讨论都是建立在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)
- 如果当前点不为'.',l[x][y]=0;
- 否则, 如果该点左侧为'.',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;
}