Codeforces Round #513(Div.1+Div.2)
闲谈:
重新写博客的第一场比赛,感觉炸裂,成功被Rose和xgcD飞
A
题目:
给出一段长为n个数字字符串,求出能用里面的字符来构成多少个长度为11且开头字符为8的字符串
题解:
直接在n/11和8出现的数量中取min就可以了
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; char st[110]; int sum[11]; int main() { int n; scanf("%d",&n); scanf("%s",st+1); memset(sum,0,sizeof(sum)); for(int i=1;i<=n;i++) sum[st[i]-'0']++; if(sum[8]==0){printf("0 ");return 0;} printf("%d ",min(sum[8],n/11)); return 0; }
B
题目:
给出一个数n,要求求出a,b,满足n=a+b,且a的数字和与b的数字和的和最大,求出最大和
题解:
直接贪心,让最接近n的...999这样的数作为a,如:n=345,则a就为299,然后将n减去a,得到b,然后再计算数字和,这个数字和一定最大,自行yy
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; int cnt[21]; LL bin[21]; int main() { LL n; scanf("%lld",&n); bin[0]=1; for(int i=1;i<=13;i++) bin[i]=bin[i-1]*10LL; LL x=n;int tot=0; while(x!=0){cnt[++tot]=x%10;x/=10;} LL ans=0;ans+=cnt[tot]-1+(tot-1)*9; n-=bin[tot-1]*LL(cnt[tot])-1; tot=0; while(n!=0){ans+=n%10;n/=10;} printf("%lld ",ans); return 0; }
C
题目:
给出一个长度为n的数组a,和一个长度为m的数组b,和一个变量x
已知c[i][j]=a[i]*b[j],求出x1,x2,y1,y2满足$sum_{i=x1}^{x2}sum_{j=y1}^{y2}c[i][j]<=x$
求出最大的(x2-x1+1)*(y2-y1+1)
题解:
一开始转换成矩阵还更不会做了,我们会发现得到的满足条件的矩阵实际上是$sum_{i=x1}^{x2}a[i]*sum_{i=y1}^{y2}b[i]$
然后我们预处理出b数组所有的子段信息,包括子段长度和子段和,存入一个结构体
按照和从小到大排序,然后用一个数组len保存前i个子段的最大长度
我们枚举x1,x2,得到$d=sum_{i=x1}^{x2}a[i]$,然后用x/d,二分找最接近x/d而且小于等于x/d的子段和,保存位置,因为我们能满足当前位置的子段,说明也能满足前面位置的子段(因为已经按照和从小到大排序了),那么就直接找到这个位置的len,用(x2-x1+1)*len[二分得到的位置]来更新答案即可
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; LL a[2100],b[2100],s[2100],sb[2100]; struct node { LL d,len; }B[4100000]; bool cmp(node n1,node n2){return n1.d<n2.d;} LL Max[4100000]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&a[i]),s[i]=a[i]+s[i-1]; for(int i=1;i<=m;i++) scanf("%lld",&b[i]),sb[i]=sb[i-1]+b[i]; int tot=0; for(int i=1;i<=m;i++) { for(int j=i;j<=m;j++) B[++tot]=(node){sb[j]-sb[i-1],j-i+1}; } sort(B+1,B+tot+1,cmp); for(int i=1;i<=tot;i++) Max[i]=max(Max[i-1],B[i].len); LL x;scanf("%lld",&x); LL mmax=0; for(int i=1;i<=n;i++) { for(int j=i;j<=n;j++) { LL d=x/(s[j]-s[i-1]); int l=1,r=tot,ans=0; while(l<=r) { int mid=(l+r)/2; if(B[mid].d<=d) l=mid+1,ans=mid; else r=mid-1; } mmax=max(mmax,(j-i+1)*Max[ans]); } } printf("%lld ",mmax); return 0; }
D(*)
题目:
有很多张椅子,若干个椅子排成一圈,可以排成多个圈
有n个人,每个人都要坐一个椅子,而且每个人给出l[i],r[i],表示他坐的位置左边要至少有l[i]个空椅子,右边要至少有r[i]个空椅子
求出至少要用多少个椅子才能满足这n个人的要求
题解:
贪心,将l和r分别从小到大排序,ans+=max(l[i],r[i]),最后加上n就行了
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; int l[110000],r[110000]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]); sort(l+1,l+n+1);sort(r+1,r+n+1); LL ans=0; for(int i=1;i<=n;i++) ans+=max(l[i],r[i]); ans+=n; printf("%lld ",ans); return 0; }
E(*)
题目:
给出一棵n个点的树,两个点之间的距离为(两个点之间的边数+1)/2(向下取整)
求出所有点对的距离和
题解:
树形DP
s[i][k]表示第i棵子树内(不包括i点),(到i点的边数+1)%2=k的点数
d[i][k]表示第i棵子树内(不包括i点),(到i点的边数+1)%2=k的点到i点的距离和
然后分情况转移就行了
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; struct node { int x,y,next; }a[410000];int len,last[210000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } LL s[210000][2],d[210000][2],ans[210000]; //s[i][k]表示第i棵子树内(不包括i点),(到i点的边数+1)%2=k的点数 //d[i][k]表示第i棵子树内(不包括i点),(到i点的边数+1)%2=k的点到i点的距离和 void dfs(int x,int fa) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y==fa) continue; dfs(y,x); ans[x]+=ans[y]; ans[x]+=d[x][0]*s[y][1]+d[y][1]*s[x][0]; ans[x]+=d[x][1]*s[y][0]+d[y][0]*s[x][1]; ans[x]+=d[x][0]*s[y][0]+d[y][0]*s[x][0]; ans[x]+=(d[x][1]+s[x][1])*s[y][1]+d[y][1]*s[x][1]; ans[x]+=d[x][0]+d[x][1]+s[x][1]; s[x][0]+=s[y][1]+1; d[x][0]+=d[y][1]+s[y][1]+1; s[x][1]+=s[y][0]; d[x][1]+=d[y][0]; } ans[x]+=d[x][0]+d[x][1]; } int main() { int n; scanf("%d",&n); len=0;memset(last,0,sizeof(last)); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); ins(x,y);ins(y,x); } dfs(1,0); printf("%lld ",ans[1]); return 0; }