Codeforces Round #304 (Div. 2)
这次打得较差,差点就绿了。。。
B题,这B题竟然WA了,再看看就发现一个很严重的错误。。--!
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int num[3050]; int main(){ int n; while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;i++){ scanf("%d",&num[i]); } sort(num,num+n); int cnt=0,ans=0; for(int i=1;i<n;i++){ if(num[i]==num[i-1]){ cnt++; } else { int k=num[i]-num[i-1]-1; if(k>=cnt){ ans=ans+(1+cnt)*cnt/2; cnt=0; } else{ ans=ans+(1+k)*k/2; cnt-=k; } ans=ans+cnt*(k+1); } } if(cnt>0){ ans=ans+(1+cnt)*cnt/2; } printf("%d\n",ans); } return 0; }
D题,可以预处理出各个数个含的质数的个数,可以用循环处理,求前缀和。循环是,从2开始,d记录下它有没有质因子,d=0则证明它当前是素数,第二层对j=i*k这样的数求它含有i的个数。如果d不为0,说明它不是素数,且由于一直循环,所以处理到它时就是已经把它所有质因子个数算出来了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long using namespace std; const int N=5000000; int d[N+10]; int s[N+10]; void initial(){ memset(d,0,sizeof(d)); s[0]=s[1]=0; for(int i=2;i<=N;i++){ if(d[i]==0){ d[i]++; for(int j=i+i;j<=N;j+=i){ int c=j; while(c%i==0){ d[j]++; c/=i; } } } s[i]=s[i-1]+d[i]; } } int main(){ initial(); int T,a,b; scanf("%d",&T); while(T--){ scanf("%d%d",&a,&b); printf("%d\n",s[a]-s[b]); } return 0; }
E题,二分图网络流
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; /* 这道在开始也在想网络流,但是,看到只能移动一条边时,就无语了。。群里一讨论,对哦,二分图拆点建边, 这样就是一条边了。。。T_T我果然是渣。。 s->i建一条a[i]的边,i+n->e建一条b[i]的边。u-v就按u->v',v->u'。 注意加上u->u' */ const int INF=0x3f3f3f3f; const int MAXN=300;//点数的最大值 const int MAXM=2000;//边数的最大值 struct Node { int from,to,next; int cap; }edge[MAXM]; int tol; int dep[MAXN];//dep为点的层次 int head[MAXN]; int flow[MAXN][MAXN]; int n,m; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w)//第一条变下标必须为偶数 { edge[tol].from=u; edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].from=v; edge[tol].to=u; edge[tol].cap=0; edge[tol].next=head[v]; head[v]=tol++; } int BFS(int start,int end) { int que[MAXN]; int front,rear; front=rear=0; memset(dep,-1,sizeof(dep)); que[rear++]=start; dep[start]=0; while(front!=rear) { int u=que[front++]; if(front==MAXN)front=0; for(int i= head[u];i!=-1; i=edge[i].next) { int v=edge[i].to; if(edge[i].cap>0&& dep[v]==-1) { dep[v]=dep[u]+1; que[rear++]=v; if(rear>=MAXN) rear=0; if(v==end)return 1; } } } return 0; } int dinic(int start,int end) { int res=0; int top; int stack[MAXN];//stack为栈,存储当前增广路 int cur[MAXN];//存储当前点的后继 while(BFS(start,end)) { memcpy(cur,head, sizeof(head)); int u=start; top=0; while(1) { if(u==end) //到达汇点 { int min=INF; int loc; for(int i=0;i<top;i++) if(min>edge[stack[i]].cap) { min=edge[stack[i]].cap; loc=i; } for(int i=0;i<top;i++){ edge[stack[i]].cap-=min; edge[stack[i]^1].cap+=min; } res+=min; top=loc; // 以最小边的起点为源点再寻找其他增广路径 u=edge[stack[top]].from; } for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next) //寻找可增广的路径,即确定edge[]中以u为起点可增广的i的第一条边的位置 if(edge[i].cap!=0 && dep[u]+1==dep[edge[i].to]) break; if(cur[u]!=-1) { stack [top++]=cur[u]; u=edge[cur[u]].to; } else { if(top==0) break; //不能再增广 dep[u]=-1; u= edge[stack [--top] ].from; //退栈寻找下一条 } } } return res; } int bef[MAXN],aft[MAXN]; int main(){ int s,e; while(scanf("%d%d",&n,&m)!=EOF){ init(); int sum=0; s=0; e=2*n+1; memset(flow,0,sizeof(flow)); for(int i=1;i<=n;i++){ scanf("%d",&bef[i]); sum+=bef[i]; } int cp=sum; for(int i=1;i<=n;i++){ scanf("%d",&aft[i]); sum-=aft[i]; } for(int i=1;i<=n;i++){ addedge(s,i,bef[i]); addedge(i+n,e,aft[i]); addedge(i,i+n,INF); } int u,v; for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); addedge(u,v+n,INF); addedge(v,u+n,INF); } if(sum!=0){ printf("NO"); } else{ int res=dinic(s,e); if(res!=cp){ puts("NO"); } else{ puts("YES"); for(int i=n+1;i<=2*n;i++){ int v=i-n; for(int ei=head[i];ei!=-1;ei=edge[ei].next){ int u=edge[ei].to; if(u<e){ flow[u][v]=edge[ei].cap; } } } for(int i=1;i<=n;i++){ printf("%d",flow[i][1]); for(int j=2;j<=n;j++) printf(" %d",flow[i][j]); printf("\n"); } } } } }