A - Keyboard
签到题1
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int main()
{IO;int T=1;//cin>>T;while(T--){char x,y;cin>>x>>y;if(x=='Y') cout<<char(y-32)<<'\n';else cout<<y<<'\n';}return 0;}
B - Futon
对于每个.
我们只考虑向右和向下能不能放置即可,这样计数不会重复。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=110;
char g[N][N];
int n,m;
int main()
{IO;int T=1;//cin>>T;while(T--){cin>>n>>m;for(int i=1;i<=n;i++) cin>>g[i]+1;int res=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(g[i][j]=='#') continue;if(i<n&&g[i+1][j]=='.') res++;if(j<m&&g[i][j+1]=='.') res++;}cout<<res<<'\n';}return 0;}
C - Neq Min
维护一个cnt[]
和当前答案res
,来一个数就添加一个数,答案扫描cnt[]
数组即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int a[N],n;
int cnt[N];
int main()
{IO;int T=1;//cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];int res=0;for(int i=1;i<=n;i++){cnt[a[i]]++;while(cnt[res]) res++;cout<<res<<'\n';}}return 0;
}
D - Squares
大佬题解
方法非常巧妙投影,举体解释可以参考上述题解。
如果两个正方形在二维平面内相交,那么将两个正方形投影到x轴上会出现两条线段,这两条线段一定相交,同理投影到y轴也一定相交。
由上述性质不难看出我们只需要计算两条线段相交或者不相交的方案数,这个是非常容易的可以参考上述题解的方法。
那么最后答案一定是:X轴不相交的方案数(Y轴随意)+++ X轴相交但是Y不相交的方案数
或者是:总方案数−-−X轴相交且Y轴相交的方案数
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
int main()
{IO;int T=1;cin>>T;while(T--){ll n,a,b;cin>>n>>a>>b;ll res=0;ll d=n-a-b;if(d>=0){ll x=(d+1)*(d+2)%mod;ll y=n-a+1;ll z=n-b+1;res=2*x*y%mod*z%mod-x*x%mod;res=(res%mod+mod)%mod;}cout<<res<<'\n';}return 0;
}
D题非常数学,当时这个投影的方法还是非常巧妙的,学习了
E - Lamps
刚开始TLE了,做了个预处理就A了
会做F题不会D的菜鸡
不难想到要单独考虑每一个.
点最答案的贡献
不妨设.
的数量是cnt
如果g[i][j]=='.'
那么考虑什么情况下对答案有贡献?如果能够点亮该点的点数量是w
那么最终这个点对答案的贡献即是(2w−1)2cnt−w(2^w-1)2^{cnt-w}(2w−1)2cnt−w,只要能点亮该点的一个点点亮即可,不能控制该点的随意。
然后预处理每个点能由多少个点点亮即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2010;
const ll mod=1e9+7;
char g[N][N];
int n,m;
ll base[N*N];
int w[N][N];
int main()
{IO;int T=1;//cin>>T;while(T--){cin>>n>>m;for(int i=1;i<=n;i++) cin>>g[i]+1;int cnt=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) cnt+=(int)g[i][j]=='.';base[0]=1;for(int i=1;i<=cnt;i++) base[i]=base[i-1]*2%mod;// 预处理数组for(int i=1;i<=n;i++){int j=1;while(j<=m){while(g[i][j]=='#') j++;int now=1,k=1;while(j+k<=m&&g[i][j+k]=='.') now++,k++;for(int p=j;p<j+k;p++) w[i][p]+=now;j=j+k;}}for(int i=1;i<=m;i++){int j=1;while(j<=n){while(g[j][i]=='#') j++;int now=1,k=1;while(j+k<=n&&g[j+k][i]=='.') now++,k++;for(int p=j;p<j+k;p++) w[p][i]+=now;j=j+k;}}// 计算答案ll res=0;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(g[i][j]=='#') continue;int now=w[i][j]-1;res=(res+(base[now]-1)*base[cnt-now]%mod)%mod;}}cout<<(ll)(res+mod)%mod<<'\n';}return 0;
}
F可能会补~~~
要加哟哦