Educational Codeforces Round 24 题解
A:
考你会不会除法
//By SiriusRen #include <bits/stdc++.h> using namespace std; #define int long long int n,k; signed main(){ scanf("%I64d%I64d",&n,&k); int t=n/(2*(k+1)); printf("%I64d %I64d %I64d\n",t,t*k,n-t*(k+1)); }
B:
按照题意模拟
竟然挂了三次......
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=105; int n,m,l[N],a[N],stk[N],top,vis[N]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d",&l[i]); } for(int i=2;i<=m;i++){ int dis=(l[i]-l[i-1]+n)%n; if(dis==0)dis=n; if(!a[l[i-1]]||a[l[i-1]]==dis)a[l[i-1]]=dis; else {puts("-1");return 0;} } for(int i=1;i<=n;i++){ if(!a[i])continue; if(!vis[a[i]])vis[a[i]]=1; else {puts("-1");return 0;} } for(int i=1;i<=n;i++)if(!vis[i])stk[++top]=i; for(int i=1;i<=n;i++){ if(a[i])printf("%d ",a[i]); else printf("%d ",stk[top--]); } }
C:
四个方向搞一个前缀和 注意大于小于 加一减一 算没算上自己 等等细节
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=100050; int d,n,m,suml[N],sumr[N],sumu[N],sumd[N],cntl,cntr,cntu,cntd; struct Node{ int x1,y1,x2,y2;Node(){} Node(int X1,int Y1,int X2,int Y2){x1=X1,y1=Y1,x2=X2,y2=Y2;} }node[N]; int main(){ scanf("%d%d%d",&d,&n,&m); for(int i=1;i<=d;i++){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2),node[i]=Node(x1,y1,x2,y2); }scanf("%d%d%d%d",&cntl,&cntr,&cntu,&cntd); for(int i=1;i<=d;i++) suml[min(node[i].x1,node[i].x2)]++,sumr[max(node[i].x1,node[i].x2)]++, sumu[min(node[i].y1,node[i].y2)]++,sumd[max(node[i].y1,node[i].y2)]++; for(int i=1;i<=n;i++)suml[i]+=suml[i-1]; for(int i=n;~i;i--)sumr[i]+=sumr[i+1]; for(int i=1;i<=m;i++)sumu[i]+=sumu[i-1]; for(int i=m;~i;i--)sumd[i]+=sumd[i+1]; for(int i=1;i<=d;i++){ int a=suml[max(node[i].x1,node[i].x2)-1],b=sumr[min(node[i].x1,node[i].x2)+1], c=sumu[max(node[i].y1,node[i].y2)-1],d=sumd[min(node[i].y1,node[i].y2)+1]; node[i].x1!=node[i].x2?a--,b--:0; node[i].y1!=node[i].y2?c--,d--:0; if(a==cntl&&b==cntr&&c==cntu&&d==cntd){printf("%d\n",i);exit(0);} }puts("-1"); }
D:
筛一次 就好了 最后判一下出现的所有数
//By SiriusRen #include <bits/stdc++.h> using namespace std; int n,a,c[1000500],num[1000500],vis[1000500]; int main(){ scanf("%d%d",&n,&a); for(int i=1;i<=n;i++){ scanf("%d",&c[i]); if(c[i]!=a&&num[c[i]]<num[a])vis[c[i]]=1; num[c[i]]++; if(c[i]!=a&&num[c[i]]<num[a])vis[c[i]]=1; } if(!num[a]){printf("%d\n",(a+1)%1000000);return 0;} for(int i=1;i<=n;i++){ if(c[i]!=a&&num[c[i]]<num[a])vis[c[i]]=1; if(c[i]!=a&&!vis[c[i]]){printf("%d\n",c[i]);return 0;} } puts("-1"); }
E:
分解质因数 two pointers一发
//By SiriusRen #include <bits/stdc++.h> using namespace std; int n,k,a[105],b[105],cnt,p[100050],tmp; void insert(int x,int y){ for(int i=1;i<=cnt;i++)while(x%a[i]==0){ if(!b[i]&&y==1)tmp++; if(y==-1&&b[i]==1)tmp--; b[i]+=y,x/=a[i]; } } int main(){ scanf("%d%d",&n,&k); int now=k; for(int i=2;i*i<=k;i++)if(now%i==0){ a[++cnt]=i; while(now%i==0)now/=i,b[cnt]++; } if(now>1)a[++cnt]=now,b[cnt]=1;tmp=cnt; for(int i=1;i<=n;i++)scanf("%d",&p[i]); long long ans=0; for(int i=1,j=1;i<=n;i++){ for(;j<=i;j++)insert(p[j],-1); for(;j<=n&&tmp;j++)insert(p[j],-1); if(!tmp)ans+=n-j+2; insert(p[i],1); }printf("%I64d\n",ans); }
F:
三分答案 特判一下前几个数 后面的肯定是 一坨 加一个链
//By SiriusRen #include <bits/stdc++.h> using namespace std; #define int long long int cases,xx; int f(int x){return x*(x-1)/2;} signed main(){ scanf("%I64d",&cases); while(cases--){ scanf("%I64d",&xx); if(xx==1){puts("0");continue;} int l=0,r=xx,ans=0; while(l<r){ int mid=(l+r)/2,edges=mid*(mid-1)/2,bridge=xx-mid; if(bridge>edges)l=mid+1,ans=max(ans,edges+bridge); else r=mid,ans=max(ans,2*bridge); }printf("%I64d\n",ans); } }
G:
费用流
拆点建图
i->i+n 连流量1 费用-1 流量ing 费用0
记录上一个%7=i的数是谁
记录每个数最后出现的位置
for(int i=1;i<=n;i++)add(0,i,0,inf),add(i+n,T,0,inf),add(i,i+n,-1,1),add(i,i+n,0,inf);
for(int i=1;i<=n;i++){
if(pos[a[i]-1])add(pos[a[i]-1]+n,i,0,inf);
if(pos[a[i]+1])add(pos[a[i]+1]+n,i,0,inf);
if(lst[a[i]%7])add(lst[a[i]%7]+n,i,0,inf);
pos[a[i]]=i,lst[a[i]%7]=i;
}add(S=n*2+2,0,0,4);
最后限制起点流出的流量是4
//By SiriusRen #include <bits/stdc++.h> using namespace std; #define mem(x,y) memset(x,y,sizeof(x)) const int N=6050,M=3050*6050,inf=0x3f3f3f3f; int first[N],nxt[M],v[M],cost[M],edge[M],tot,n,a[N],S,T,vis[N],dis[N],with[N],minn[N],pos[M],lst[M],ans; void Add(int x,int y,int C,int E){cost[tot]=C,edge[tot]=E,v[tot]=y,nxt[tot]=first[x],first[x]=tot++;} void add(int x,int y,int C,int E){Add(x,y,C,E),Add(y,x,-C,0);} bool tell(){ queue<int>q;q.push(S); mem(dis,0x3f),mem(with,0),mem(minn,0x3f),mem(vis,0);dis[S]=0; while(!q.empty()){ int t=q.front();q.pop();vis[t]=0; for(int i=first[t];~i;i=nxt[i]) if(dis[v[i]]>dis[t]+cost[i]&&edge[i]){ dis[v[i]]=dis[t]+cost[i],minn[v[i]]=min(minn[t],edge[i]),with[v[i]]=i; if(!vis[v[i]])vis[v[i]]=1,q.push(v[i]); } }return dis[T]<inf; } int zeng(){ for(int i=T;i!=S;i=v[with[i]^1]) edge[with[i]]-=minn[T],edge[with[i]^1]+=minn[T]; return minn[T]*dis[T]; } int main(){ memset(first,-1,sizeof(first)); scanf("%d",&n),T=2*n+1; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++)add(S,i,0,inf),add(i+n,T,0,inf),add(i,i+n,-1,1),add(i,i+n,0,inf); for(int i=1;i<=n;i++){ if(pos[a[i]-1])add(pos[a[i]-1]+n,i,0,inf); if(pos[a[i]+1])add(pos[a[i]+1]+n,i,0,inf); if(lst[a[i]%7])add(lst[a[i]%7]+n,i,0,inf); pos[a[i]]=i,lst[a[i]%7]=i; }add(S=n*2+2,0,0,4); while(tell())ans+=zeng(); printf("%d\n",-ans); }