Codeforces Round #551 Div. 2
Posted gloid
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #551 Div. 2相关的知识,希望对你有一定的参考价值。
A:签到。没仔细看数据范围,看到一个O(nt)的差点叉上去了。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 110 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,a[N],b[N]; signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(),m=read(); int ans=1000000,ansi=0; for (int i=1;i<=n;i++) { a[i]=read(),b[i]=read(); if (a[i]<m) a[i]+=b[i]*((m-a[i]-1)/b[i]+1); if (a[i]<ans) ans=a[i],ansi=i; } cout<<ansi; return 0; //NOTICE LONG LONG!!!!! }
B:从大到小考虑每个数,放在所有能放但还没有放的位置上即可。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 110 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,h,a[N],b[N],c[N][N],d[N][N]; signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(),m=read(),h=read(); for (int i=1;i<=m;i++) b[i]=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) c[i][j]=read(); for (int i=h;i>=1;i--) for (int x=1;x<=n;x++) for (int y=1;y<=m;y++) if (c[x][y]&&i<=a[x]&&i<=b[y]&&!d[x][y]) d[x][y]=i; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) cout<<d[i][j]<<‘ ‘; cout<<endl; } return 0; //NOTICE LONG LONG!!!!! }
C:在右括号够的情况下尽量放左括号。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 300010 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,c[N][2];char s[N]; signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(); scanf("%s",s+1); for (int i=n;i>=1;i--) { c[i][0]=c[i+1][0],c[i][1]=c[i+1][1]; if (s[i]==‘(‘) c[i][0]++; if (s[i]==‘)‘) c[i][1]++; } int cnt=0; for (int i=1;i<=n;i++) { if (s[i]==‘(‘) cnt++; else if (s[i]==‘)‘) cnt--; else { if (n-i-c[i][0]<cnt+c[i][0]+1) s[i]=‘)‘,cnt--; else s[i]=‘(‘,cnt++; } if (cnt<0||cnt==0&&i<n) goto err; } if (cnt>0) goto err; printf("%s",s+1); return 0; err:cout<<":("; //NOTICE LONG LONG!!!!! }
D:这种东西容易想到二分答案,转化成01问题后,设f[i]为要让i号点为1其子树内至少有几个叶子为1,转移显然。dp完之后可以发现压根不需要二分答案。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 300010 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,a[N],b[N],p[N],f[N],fa[N],t,leaves; struct data{int to,nxt; }edge[N]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} void dfs(int k) { for (int i=p[k];i;i=edge[i].nxt) dfs(edge[i].to); if (!p[k]) leaves++,f[k]=1; else if (a[k]) { f[k]=N; for (int i=p[k];i;i=edge[i].nxt) f[k]=min(f[k],f[edge[i].to]); } else { f[k]=0; for (int i=p[k];i;i=edge[i].nxt) f[k]+=f[edge[i].to]; } } signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=2;i<=n;i++) { fa[i]=read(); addedge(fa[i],i); } dfs(1); cout<<leaves-f[1]+1; return 0; err:cout<<":("; //NOTICE LONG LONG!!!!! }
E:询问每一行,考虑其答案的奇偶性,若有奇数,一定有两行均为奇数,头和尾就在这两行内;若没有奇数,说明头和尾在同一行,再询问每一列找到在哪两列即可。确定行/列后直接二分即可。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 1010 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n; signed main() { n=read(); int x=0,y=0; for (int i=1;i<=n;i++) { if (x==0&&i==n) break; cout<<‘?‘<<‘ ‘<<i<<‘ ‘<<1<<‘ ‘<<i<<‘ ‘<<n<<endl; int u=read(); if (u&1) if (x) y=i;else x=i; } if (!x) { int ansx[3],ansy[3],cnt=0; for (int i=1;i<=n;i++) { cout<<‘?‘<<‘ ‘<<1<<‘ ‘<<i<<‘ ‘<<n<<‘ ‘<<i<<endl; int u=read(); if (u&1) { int l=1,r=n; while (l<r) { int mid=l+r>>1; cout<<"?"<<‘ ‘<<l<<‘ ‘<<i<<‘ ‘<<mid<<‘ ‘<<i<<endl; int u=read(); if (u&1) r=mid; else l=mid+1; } cnt++;ansx[cnt]=l,ansy[cnt]=i; } } cout<<"!"; for (int i=1;i<=cnt;i++) cout<<‘ ‘<<ansx[i]<<‘ ‘<<ansy[i]; } else { int ansx[3],ansy[3],cnt=0; int i=x; int l=1,r=n; while (l<r) { int mid=l+r>>1; cout<<"?"<<‘ ‘<<i<<‘ ‘<<l<<‘ ‘<<i<<‘ ‘<<mid<<endl; int u=read(); if (u&1) r=mid; else l=mid+1; } cnt++;ansx[cnt]=i,ansy[cnt]=l; i=y; l=1,r=n; while (l<r) { int mid=l+r>>1; cout<<"?"<<‘ ‘<<i<<‘ ‘<<l<<‘ ‘<<i<<‘ ‘<<mid<<endl; int u=read(); if (u&1) r=mid; else l=mid+1; } cnt++;ansx[cnt]=i,ansy[cnt]=l; cout<<"!"; for (int i=1;i<=cnt;i++) cout<<‘ ‘<<ansx[i]<<‘ ‘<<ansy[i]; } return 0; //NOTICE LONG LONG!!!!! }
F:不妨设总长度为1,最后再乘l即可。考虑坐标为i的点的贡献,其被k条线段覆盖的概率是C(n,k)pn-k(1-p)k,其中p=i2+(1-i)2=2i2-2i+1。对每个k暴力积分即可,直接暴力进行多项式运算。可能略卡常。场上居然以为积分求逆元要带log,自闭了。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 2010 #define P 998244353 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,k,l,ans,C[N][N],f[N<<1],h[N<<1],Inv[N<<1],g[N]; int ksm(int a,int k) { int s=1; for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P; return s; } int inv(int a){return ksm(a,P-2);} void inc(int &x,int y){x+=y;if (x>=P) x-=P;} void mul(int m,int *f,int *g,int n) { memset(h,0,sizeof(h)); for (int i=0;i<=m;i++) for (int j=0;j<min(i+1,n);j++) inc(h[i],1ll*f[i-j]*g[j]%P); for (int i=0;i<=m;i++) f[i]=h[i]; } void div(int m,int *f,int *g,int n) { h[2]=f[m],h[1]=f[m-1];f[m]=f[m-1]=0; int x=inv(g[2]); for (int i=m-2;i>=0;i--) { h[0]=f[i]; f[i]=1ll*h[2]*x%P; h[2]=(h[1]+P-1ll*g[1]*f[i]%P)%P; h[1]=(h[0]+P-1ll*g[0]*f[i]%P)%P; } } int calc() { int s=0; for (int i=1;i<=n*2+1;i++) inc(s,1ll*f[i-1]*Inv[i]%P); return s; } signed main() { n=read(),k=read(),l=read(); C[0][0]=1; for (int i=1;i<=n;i++) { C[i][0]=1; for (int j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%P; } Inv[0]=Inv[1]=1;for (int i=2;i<=n*2+4;i++) Inv[i]=P-1ll*(P/i)*Inv[P%i]%P; f[0]=1; g[0]=0,g[1]=2,g[2]=P-2; for (int i=1;i<=k;i++) mul(i*2,f,g,3); g[0]=1,g[1]=P-2,g[2]=2; for (int i=1;i<=n-k;i++) mul((i+k)*2,f,g,3); inc(ans,1ll*C[n][k]*calc()%P); for (int i=k+1;i<=n;i++) { g[0]=1,g[1]=P-2,g[2]=2; div(n*2,f,g,3); g[0]=0,g[1]=2,g[2]=P-2; mul(n*2,f,g,3); inc(ans,1ll*C[n][i]*calc()%P); } ans=1ll*ans*l%P; cout<<ans; return 0; //NOTICE LONG LONG!!!!! }
小号打的。result:rank 27 rating +222
以上是关于Codeforces Round #551 Div. 2的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #551 (Div. 2) 题解
Codeforces Round #551 (Div. 2)
Codeforces Round #551 (Div. 2)A. Serval and Bus