ATcoder ABC 358 补题记录(A~D,G)
A
直接模拟即可。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000100,mod=998244353;
int a[N];
signed main(){
string s,t;
cin>>s>>t;
if(s=="AtCoder"&&t=="Land")cout<<"Yes\n";
else cout<<"No\n";
}
B
直接模拟即可。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000100,mod=998244353;
int a[N];
signed main(){
int n,t;
cin>>n>>t;
for(int i=1;i<=n;i++)cin>>a[i];
int now=-1e18;
for(int i=1;i<=n;i++){
int xu=now;
if(xu<=a[i])now=a[i]+t;
else now=xu+t;
cout<<now<<'\n';
}
}
C
发现 \(n\) 很小,所以直接暴力枚举每一个状态,并判断这个状态是否可以覆盖所有的爆米花。如果可以覆盖那么当前状态的位数就是当前所用的摊位的数量。取最小值即可。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000100,mod=998244353;
char s[3010][3010];
signed main(){
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)scanf("%s",s[i]);
int cost=233;
for(int i=1;i<(1ll<<n);i++){
set<int>se;
for(int j=0;j<n;j++)if(i>>j&1)
for(int k=0;k<m;k++)if(s[j][k]=='o')
se.insert(k);
if(se.size()==m)cost=min(cost,(int)__builtin_popcountll(i));
}
cout<<cost<<'\n';
}
D
对于每一个人 \(i\),使用 multiset
找到让她可以满足的,价值最小的礼物分配给她。时间复杂度为 \(O(n\log n)\)。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000100,mod=998244353;
int a[N],b[N];
signed main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++)cin>>b[i];
multiset<int>se;
int res=0;
for(int i=1;i<=n;i++)se.insert(a[i]);
sort(a+1,a+n+1,greater<>());
for(int i=1;i<=m;i++){
auto it=se.lower_bound(b[i]);
// cout<<"dbg "<<i<<' '<<b[i]<<'\n';
if(it==se.end()){
res=-1;
break;
}
res+=*it;
se.erase(it);
}
cout<<res<<'\n';
}
G
实际上 CF57E 也有一个(有点)类似的结论。
容易发现 \(n\times m\) 步之后一定可以到达任意的一个结点。因此 \(n\times m\) 步之后一定是停在某一个结点攒贡献。所以设 \(f_{i,j,k}\) 表示当前走了 \(i\) 步,目前位于结点 \((j,k)\) 的最大收益。很显然每一个 \(f_{i,j,k}\) 都可以从 \((j,k)\) 结点本身和 \((j,k)\) 结点四连通的结点转移而来。
此时若 \(k\le n\times m\) 则答案已经求出,\(k>n\times m\) 则枚举最后到达的每一个结点 \((i,j)\),这个结点的最大贡献就是 \(f_{n\times m,i,j}+(n\times m-k)\times a_{i,j}\)。可能这个贡献并不一定是最大贡献,但是最大贡献一定可以通过这种方式得到。
时间复杂度为 \(O(n^2m^2)\)。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000100,mod=998244353;
int a[55][55],f[55*55][55][55];
//设f[i][j][k]表示现在是第i个操作, 当前位于(j,k)
signed main(){
int n,m,k;
cin>>n>>m>>k;
int si,sj;
cin>>si>>sj;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
memset(f,-0x3f,sizeof f);
f[0][si][sj]=0;
for(int i=1;i<=min(n*m,k);i++){
for(int j=1;j<=n;j++)
for(int k=1;k<=m;k++)
f[i][j][k]=f[i-1][j][k]+a[j][k];
for(int j=1;j<=n;j++)
for(int k=1;k<=m;k++){
const int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
for(int d=0;d<4;d++){
int x=j+dx[d],y=k+dy[d];
if(x>=1&&x<=n&&y>=1&&y<=m)
f[i][x][y]=max(f[i][x][y],f[i-1][j][k]+a[x][y]);
}
}
}
if(k<=n*m){
int res=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
res=max(res,f[k][i][j]);
cout<<res<<'\n';
}else{
int res=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
int now=f[n*m][i][j]+(k-n*m)*a[i][j];
res=max(res,now);
}
cout<<res<<'\n';
}
}
本文来自博客园,作者:yhbqwq,转载请注明原文链接:https://www.cnblogs.com/yhbqwq/p/18249845,谢谢QwQ