比賽總結
這次CF打得還不錯,比上次好很多,做了4題,其中3題都是firstblood,E題最後30分鐘纔開始做,沒做出來,B題wa了一次才ac,其間被網速殺了好幾回,好在對最後的罰時影響並不是很大。
比賽提交記錄:
最終比賽排名(含vp選手,共8445人)
在正式選手裏排名123名(正式選手共3249人)
A. Soldier and Bananas
題目鏈接
http://codeforces.com/contest/546/problem/A
題目大意
買香蕉要花
思路
水題,不說了
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long int LL;
int main()
{
LL k,w,n;
scanf("%I64d%I64d%I64d",&k,&n,&w);
LL need=(k+w*k)*w/2-n;
if(need<=0) printf("0\n");
else printf("%I64d\n",need);
return 0;
}
B. Soldier and Badges
題目鏈接
http://codeforces.com/contest/546/problem/B
題目大意
給你一個序列,每次操作你可以對一個元素加1,問最少經過多少次操作,才能使所有元素互不相同
思路
首先對序列進行排序,排序後的序列裏,我們從左到右掃一遍所有元素,若當前的元素小於等於它左邊的元素,就讓當前的元素變成它左邊的元素大小+1,如此反覆,顯然可以得到正確答案
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long int LL;
int n;
LL val[4000];
int main()
{
LL ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%I64d",&val[i]);
sort(val+1,val+n+1);
for(int i=2;i<=n;i++)
if(val[i]<=val[i-1])
{ans+=val[i-1]-val[i]+1,val[i]=val[i-1]+1;}
printf("%I64d\n",ans);
return 0;
}
C. Soldier and Cards
題目鏈接
http://codeforces.com/contest/546/problem/C
題目大意
兩個士兵做遊戲,他們手上有
思路
由於
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long int LL;
int n;
LL val[4000];
int main()
{
LL ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%I64d",&val[i]);
sort(val+1,val+n+1);
for(int i=2;i<=n;i++)
if(val[i]<=val[i-1])
{ans+=val[i-1]-val[i]+1,val[i]=val[i-1]+1;}
printf("%I64d\n",ans);
return 0;
}
D. Soldier and Number Game
題目鏈接
http://codeforces.com/contest/546/problem/D
題目大意
問
思路
實際上就是問
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define MAXN 6000000
using namespace std;
typedef long long int LL;
bool isPrime[MAXN];
int sum[MAXN];
int cnt[MAXN];
void GetPrime()
{
memset(isPrime,true,sizeof(isPrime));
isPrime[0]=isPrime[1]=false;
for(int i=2;i<MAXN;i++)
{
if(!isPrime[i]) continue;
for(int j=i+i;j<MAXN;j+=i)
{
isPrime[j]=false;
}
for(LL j=(LL)i;j<MAXN;j*=(LL)i)
for(LL t=j;t<MAXN;t+=j)
cnt[t]++;
}
for(int i=1;i<MAXN;i++)
sum[i]=sum[i-1]+cnt[i];
}
int T;
int main()
{
/*for(int i=1;i<MAXN;i++)
{
int tmp=i,nowt=0;
for(int i=2;i*i<=tmp;i++)
{
while(!tmp%i) tmp/=i,nowt++;
}
sum[i]+=nowt;
}*/
GetPrime();
//cout<<tot<<endl;
scanf("%d",&T);
while(T--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",sum[a]-sum[b]);
}
return 0;
}
E. Soldier and Traveling
題目鏈接
http://codeforces.com/contest/546/problem/E
題目大意
給你一張無向圖,每個節點
思路
顯然是個最大流問題。我們可以建立這樣一個模型:
每個點拆成入點和出點。入點代表初始時每個點的狀態,出點代表最終每個點的狀態。源點向每個點
其實這樣的一個模型很好建立,但是我還是太弱了,考場上沒想出來。。。
代碼
#include <sstream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXV 1000
#define MAXE 3000
#define MAXN 1000
#define INF 0x3f3f3f3f
using namespace std;
int S=MAXV-2,T=MAXV-1;
struct edge
{
int u,v,cap,next;
}edges[MAXE];
int head[MAXV],nCount=1;
void AddEdge(int U,int V,int C)
{
edges[++nCount].u=U;
edges[nCount].v=V;
edges[nCount].cap=C;
edges[nCount].next=head[U];
head[U]=nCount;
}
void add(int U,int V,int C)
{
AddEdge(U,V,C);
AddEdge(V,U,0);
}
int layer[MAXV],q[MAXE*2];
bool CountLayer()
{
memset(layer,-1,sizeof(layer));
int h=0,t=1;
q[h]=S;
layer[S]=1;
while(h<t)
{
int u=q[h++];
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(layer[v]==-1&&edges[p].cap)
{
layer[v]=layer[u]+1;
q[t++]=v;
}
}
}
return layer[T]!=-1;
}
int DFS(int u,int flow)
{
if(u==T) return flow;
int used=0;
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(layer[v]==layer[u]+1&&edges[p].cap)
{
int tmp=DFS(v,min(flow-used,edges[p].cap));
used+=tmp;
edges[p].cap-=tmp;
edges[p^1].cap+=tmp;
if(used==flow) return used;
}
}
if(!used) layer[u]=-1;
return used;
}
int Dinic()
{
int maxflow=0;
while(CountLayer())
maxflow+=DFS(S,INF);
return maxflow;
}
int n,m;
int a[MAXV],b[MAXV];
bool inX[MAXV];
int vec[MAXV][MAXV];
int rest[MAXV];
int main()
{
memset(head,-1,sizeof(head));
int sumA=0,sumB=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
{
add(S,i,a[i]);
add(i,i+n,INF); //!!!!
add(i+n,T,b[i]);
sumA+=a[i];
sumB+=b[i];
}
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v+n,INF);
add(v,u+n,INF);
}
if(sumA!=sumB)
{
printf("NO\n");
return 0;
}
int mf=Dinic();
if(mf!=sumB)
{
printf("NO\n");
return 0;
}
printf("YES\n");
for(int p=2;p<=nCount;p+=2)
{
if(edges[p].u==S||edges[p].u==T||edges[p].v==S||edges[p].v==T) continue;
vec[edges[p].u][edges[p].v-n]=edges[p^1].cap;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",vec[i][j]);
}
printf("\n");
}
return 0;
}