title :2022牛客暑期多校训练营6 题解
date : 2022-9-22
tags : ACM,练习记录
author : Linno
2022牛客暑期多校训练营6 题解
题目链接 :https://ac.nowcoder.com/acm/contest/33191
补题进度 :6/13
已经补不动题了。
文章目录
A-Array
可以考虑2的幂次,对于所有 a i a_i ai,我们转化成他在 2 k 2^k 2k次方个数内必须出现一次,那么这样填可以保证题目的条件满足。我们排序之后知道了m的大小,然后填法大概就是直接贪就行了,这个长度会有很多中填法。
//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e6+7;
const int mod=1e9+7;
//int read(){ int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
struct node{
int a,id;
}s[N];
bool cmp(node A,node B){
return A.a<B.a;
}
int n,cnt=0,b[N],c[N],bin[33];
void Solve(){
cin>>n;
int mi=1;
bin[0]=1;for(int i=1;i<=30;++i) bin[i]=bin[i-1]<<1;
for(int i=1;i<=n;++i){
cin>>s[i].a;
s[i].id=i;
}
sort(s+1,s+1+n,cmp);
for(int i=1;i<=n;++i){
int k=lower_bound(bin,bin+31,s[i].a)-bin;
s[i].a=bin[k-1];
}
//for(int i=1;i<=n;++i) cout<<i<<" "<<s[i].a<<" "<<s[i].id<<"\n";
int cnt=1,m=s[n].a;
for(int i=1;i<=n;++i){
while(c[cnt]) cnt++;
int now=cnt;
while(now<=m){
c[now]=s[i].id;
now+=s[i].a;
}
}
cout<<m<<"\n";
for(int i=1;i<=m;++i) cout<<max(1ll,c[i])<<" ";
cout<<"\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("in.cpp","r",stdin);
// freopen("out.cpp","w",stdout);
int T=1;
// cin>>T;
// clock_t start,finish;
// start=clock();
while(T--){
Solve();
}
// finish=clock();
// cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
return 0;
}
B-Eezie and Pie
树上差分,dfs对当前点以及k级祖先打tag,然后统计答案即可。
#include <bits/stdc++.h>
#define maxn 2000005
using namespace std;
int a[maxn],q[maxn],ans[maxn],cnt,d[maxn],n;
vector<int> f[maxn];
void dfs(int x,int fa,int dep)
{
d[x]++;
if (dep-a[x]-1>0) d[q[dep-a[x]-1]]--;
int len=f[x].size();
for (int i=0;i<len;++i)
if (f[x][i]!=fa)
{
q[++cnt]=f[x][i];
dfs(f[x][i],x,dep+1);
--cnt;
}
}
void getans(int x,int fa)
{
int len=f[x].size();
for (int i=0;i<len;++i)
if (f[x][i]!=fa)
{
getans(f[x][i],x);
ans[x]+=ans[f[x][i]];
}
ans[x]+=d[x];
}
int main()
{
cin>>n;
for (int i=1;i<n;++i)
{
int v,u;
scanf("%d%d",&u,&v);
f[u].push_back(v);
f[v].push_back(u);
}
for (int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
}
q[++cnt]=1;
dfs(1,0,1);
getans(1,0);
for (int i=1;i<=n;++i)
printf("%d ",ans[i]);
return 0;
}
G-Icon Design
搬砖题,直接看着题写就完事了。
//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;
//int read(){ int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n;
char mp[505][505]; //n+2,
void Solve(){
cin>>n;
int W=13*n+19,H=4*n+5;
for(int i=1;i<=H;++i) for(int j=1;j<=W;++j) mp[i][j]='.';
for(int i=1;i<=W;++i) mp[1][i]=mp[H][i]='*';
for(int i=1;i<=H;++i) mp[i][1]=mp[i][W]='*';
for(int i=n+2,j=0;i<=3*n+4;++i,++j) mp[i][n+3+j]=mp[i][n+3]=mp[i][3*n+5]='@'; //N
for(int i=3*n+4+(n+2)+1;i<=6*n+8+1;++i) mp[n+2][i]=mp[2*n+3][i]='@'; //F横
for(int i=n+2;i<=3*n+4;++i) mp[i][3*n+4+(n+2)+1]='@'; //F竖
for(int i=n+2;i<=3*n+4;++i) mp[i][3*n+4+(n+2)+(2*n+3)+(n+2)]='@'; //L竖
for(int i=3*n+4+(n+2)+(2*n+3)+(n+2);i<=3*n+4+(n+2)+(2*n+3)+(n+2)+(2*n+2);++i) mp[3*n+4][i]='@'; //L竖
for(int i=n+2;i<=3*n+4;++i){
int k=(i<=H/2)?0:2*n+2;
mp[i][3*n+4+(n+2)+(2*n+3)+(2*n+3)+(n+2)+(n+1)+k]='@'; //S竖
}
for(int i=3*n+4+(n+2)+(2*n+3)+(2*n+3)+(n+2)+(n+1);i<=3*n+4+(n+2)+(2*n+3)+(2*n+3)+(n+2)+(n+1)+(2*n+2);++i) mp[n+2][i]=mp[2*n+3][i]=mp[3*n+4][i]='@'; //F横
for(int i=1;i<=H;++i){
for(int j=1;j<=W;++j) cout<<mp[i][j];
cout<<"\n";
}
}
signed main(){
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
// freopen("in.cpp","r",stdin);
// freopen("out.cpp","w",stdout);
int T=1;
// cin>>T;
// clock_t start,finish;
// start=clock();
while(T--){
Solve();
}
// finish=clock();
// cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
return 0;
}
I-Line
题解区的代码,非常精妙。因为数据范围很小,我们直接对每个向量建立不同的维度,然后从(0,0)开始,对每个向量,答案都加入当前点集往这个向量的方向走th的倍数长所得的点。
#include<bits/stdc++.h>
#define pii pair<int,int>
#define F first
#define S second
#define mk make_pair
using namespace std;
int th[10];
signed main(){
th[0]=1;
for(int i=1;i<10;++i){
th[i]=th[i-1]*23;
}
int n,d;
scanf("%d%d",&n,&d);
set<pii>s,ans;
for(int i=1,x,y;i<=n;++i){
scanf("%d%d",&x,&y);
int d=__gcd(x,y);
s.insert(mk(x/d,y/d)); //插入向量
}
ans.insert(mk(0,0));
int id=-1;
for(auto dir:s){ //对于所有向量
++id; //th都要取不同的方向
auto t=ans;
for(auto i:t){
for(int j=1;j<d;++j){ //取其中d个点
ans.insert(mk(i.F+j*dir.F*th[id],i.S+j*dir.S*th[id])); //插入点集
}
}
}
printf("%d\n",ans.size());
for(auto i:ans) printf("%d %d\n",i.F,i.S);
return 0;
}
J-Number Game
我们可以做很多次变换,但实际上结果只有几种而已,分类讨论就行。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b,c,x;
int main () {
int t ;
scanf("%d",&t);
while(t--) {
scanf("%lld%lld%lld%lld",&a,&b,&c,&x);
ll x1=x-c;
ll x2=x+c+b-a;
if(x==c||x==b-c||x==a-b-c) {
puts("Yes");
continue;
}
if(a==2ll*b) {
puts("No");
continue;
}
if((x1%(a-2ll*b)==0)||(x2%(2ll*b-a)==0)) {
puts("Yes");
} else puts("No");
}
}
M-Z-Game on grid
从(1,1)到(n,m)dp一次去得到每个格子是否能转化为某种局面,复杂度是 O ( n m ) O(nm) O(nm)的,我们只需要做三次就可以了。这里推荐ygg的题解,非常简单易懂。
#include <bits/stdc++.h>
using namespace std;
int T,n,m,f[505][505],g[505][505],ans[10];
char a[505][505];
void towin() {
for (int i=0; i<=n+1; i++)
for (int j=0; j<=m+1; j++)
f[i][j]=g[i][j]=0;
int flag=0;
if (a[n][m]=='.') {
flag=1;
a[n][m]='B';
}
for (int i=n; i>=1; i--)
for (int j=m; j>=1; j--)
if ((i+j)&1) { //Bob走的点
if (a[i][j]=='B') g[i][j]=1;
if (a[i][j]=='A') g[i][j]=-1;
if (a[i][j]=='.') {
if (i==n) {
if (f[i][j+1]==1) g[i][j]=-1;
else g[i][j]=1;
} else if (j==m) {
if (f[i+1][j]==1) g[i][j]=-1;
else g[i][j]=1;
} else {
if (f[i+1][j]==1&&f[i][j+1]==1) g[i][j]=-1;
else g[i][j]=1;
}
}
} else {
if (a[i][j]=='A') f[i][j]=1;
if (a[i][j]=='B') f[i][j]=-1;
if (a[i][j]=='.') {
if (i==n) {
if (g[i][j+1]==1) f[i][j]=-1;
else f[i][j]=1;
} else if (j==m) {
if (g[i+1][j]==1) f[i][j]=-1;
else f[i][j]=1;
} else {
if (g[i][j+1]==1&&g[i+1][j]==1) f[i][j]=-1;
else f[i][j]=1;
}
}
}
if (f[1][1]==1) ans[1]=1;
else ans[1]=0;
if (flag) a[n][m]='.';
}
void tolose() {
for (int i=0; i<=n+1; i++)
for (int j=0; j<=m+1; j++)
f[i][j]=g[i][j]=0;
int flag=0;
if (a[n][m]=='.') {
flag=1;
a[n][m]='A';
}
for (int i=n; i>=1; i--)
for (int j=m; j>=1; j--)
if ((i+j)&1) { //Bob走的点
if (a[i][j]=='A') g[i][j]=1;
if (a[i][j]=='B') g[i][j]=-1;
if (a[i][j]=='.') {
if (i==n) {
if (f[i][j+1]==1) g[i][j]=-1;
else g[i][j]=1;
} else if (j==m) {
if (f[i+1][j]==1) g[i][j]=-1;
else g[i][j]=1;
} else {
if (f[i+1][j]==1&&f[i][j+1]==1) g[i][j]=-1;
else g[i][j]=1;
}
}
} else {
if (a[i][j]=='B') f[i][j]=1;
if (a[i][j]=='A') f[i][j]=-1;
if (a[i][j]=='.') {
if (i==n) {
if (g[i][j+1]==1) f[i][j]=-1;
else f[i][j]=1;
} else if (j==m) {
if (g[i+1][j]==1) f[i][j]=-1;
else f[i][j]=1;
} else {
if (g[i][j+1]==1&&g[i+1][j]==1) f[i][j]=-1;
else f[i][j]=1;
}
}
}
if (f[1][1]==1) ans[3]=1;
else ans[3]=0;
if (flag) a[n][m]='.';
}
void toequal() {
if (a[n][m]!='.') return;
for (int i=0; i<=n+1; i++)
for (int j=0; j<=m+1; j++)
f[i][j]=g[i][j]=0;
f[n][m]=1;
g[n][m]=-1;
for (int i=n; i>=1; --i)
for (int j=m; j>=1; --j)
if (i==n&&j==m) continue;
else if ((i+j)&1) { //Bob走的点
if (a[i][j]=='B'||a[i][j]=='A') g[i][j]=1;
else {
if (i==n) {
if (f[i][j+1]==1) g[i][j]=-1;
else g[i][j]=1;
} else if (j==m) {
if (f[i+1][j]==1) g[i][j]=-1;
else g[i][j]=1;
} else {
if (f[i+1][j]==1&&f[i][j+1]==1) g[i][j]=-1;
else g[i][j]=1;
}
}
} else {
if (a[i][j]=='B'||a[i][j]=='A') f[i][j]=-1;
else {
if (i==n) {
if (g[i][j+1]==1) f[i][j]=-1;
else f[i][j]=1;
} else if (j==m) {
if (g[i+1][j]==1) f[i][j]=-1;
else f[i][j]=1;
} else {
if (g[i+1][j]==1&&g[i][j+1]==1) f[i][j]=-1;
else f[i][j]=1;
}
}
}
if (f[1][1]==1) ans[2]=1;
else ans[2]=0;
}
int main() {
cin>>T;
while (T--) {
scanf("%d%d",&n,&m);
for (int i=1; i<=n; ++i) {
scanf("%s",a[i]+1);
}
if (a[1][1]=='A') ans[1]=1;
else if (a[1][1]=='.') towin();
if (a[1][1]=='B') ans[3]=1;
else if (a[1][1]=='.') tolose();
toequal();
for (int i=1; i<=3; ++i)
if (ans[i]) printf("yes ");
else printf("no ");
ans[1]=ans[2]=ans[3]=0;
putchar('\n');
}
return 0;
}