# 2016 ACM-ICPC World Finals 部分题解

Problem A Balanced Diet

$S=\sum {a}_{i}$$S=\sum a_i$，对于$nfi-1$nfi-1，当nfi是非整数时有2个合法取值，nfi是整数时仅有1个合法取值，nfi是整数当且仅当n是S的倍数，此时所有糖果吃掉的个数是确定的（所以若k=aS+b，前aS天吃了什么可以无视掉），且吃掉的个数mod ai以S为循环节。

code

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<algorithm>
#define ll long long
#define pb push_back
using namespace std;

const int maxn = 110000;

int n,m,K;
int a[maxn],et[maxn];
vector<int>V[maxn];
int s[maxn],nowd[maxn];

int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);

scanf("%d%d",&m,&K);
for(int i=1;i<=m;i++) scanf("%d",&a[i]),n+=a[i];
for(int i=1;i<=K;i++) scanf("%d",&et[i]);
if(K>=n)
{
int nk=K%n;
for(int i=1;i<=nk;i++) et[i]=et[K-(nk-i)];
K=nk;
}

for(int i=1;i<=m;i++)
{
int c=a[i];
for(int j=1;j<c;j++)
{
int t=(ll)n*j/c;
if((ll)t*c<(ll)n*j) t++;
V[t].push_back(i);
}
V[n].push_back(i);
}

for(int i=1;i<=K;i++)
{
s[et[i]]++;
for(int j=0;j<(int)V[i].size();j++) nowd[V[i][j]]++;
}
int oth=0;
for(int i=K+1;i<=n;i++)
{
oth++; int ok=1;
for(int j=0;j<(int)V[i].size();j++)
{
int k=V[i][j]; nowd[k]++;
if(s[k]<nowd[k])
{
if(!oth) { ok=0; break; }
oth--; s[k]++;
}
}
if(!ok) return printf("%d\n",i-K-1),0;
}
puts("forever");

return 0;
}

Problem B Branch Assignment

Problem C Ceiling Function

Problem D Clock Breaking

Problem E Forever Young

code：

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<algorithm>
#define ll long long
#define ld long double
using namespace std;

const int maxn = 100;
const ld eps = 1e-9;

ll y,d,ub;
ll tl[maxn],tlp,t[maxn],tp;
int Big()
{
if(tp!=tlp) return tp>tlp;
for(int i=tp;i>=1;i--) if(t[i]!=tl[i])
return t[i]>tl[i];
return 1;
}
void get_ub()
{
ll tmp;
tmp=d; while(tmp) tl[++tlp]=tmp%10ll,tmp/=10ll;

ll l=2,r=y;
while(l<=r)
{
ll mid=(l+r)>>1;
tmp=y;
tp=0; while(tmp) t[++tp]=tmp%mid,tmp/=mid;
if(Big()) l=mid+1ll;
else r=mid-1ll;
}
ub=l-1ll;
}

ll Find(ll i)
{
if(i>=100)
{
ll a=i/100,b=(i/10)%10,c=i%10; c-=y;
ld delta=(ld)b*b-4.0*(ld)a*(ld)c;
if(delta>-eps)
{
delta=max(delta,(ld)0);
delta=sqrt(delta);
ld a0=(-(ld)b+delta)/(ld)(2.0*a);
ld a1=(-(ld)b-delta)/(ld)(2.0*a);
ll b0=(ll)(a0+0.5);
ll b1=(ll)(a1+0.5);

if(b0<=1||b0>ub||a*b0*b0+b*b0+c!=0) b0=-1;
if(b1<=1||b1>ub||a*b1*b1+b*b1+c!=0) b1=-1;
return max(b0,b1);
}
return -1;
}
else
{
ll a=i/10,b=i%10;
b=y-b;
return b%a==0?(b/a>ub?-1:b/a):-1;
}
}
ll b;

int main()
{
//  freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);

scanf("%lld%lld",&y,&d);
get_ub();

for(ll i=10;i<1000;i++)
b=max(b,Find(i));
for(ll i=2;i<=ub&&i<=1000000;i++)
{
int ok=1;
for(ll p=1;ok&&p<y&&p>0;p*=i)
{
if((y/p)%i>9ll) ok=0;
ld np=(ld)p*(ld)i;
if(np>(ld)y-eps) break;
}
if(ok) b=max(b,i);
}
printf("%lld\n",b);

return 0;
}

Problem F Longest Rivers

code

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<algorithm>
#define ll long long
using namespace std;

inline void read(int &x)
{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
inline void down(ll &a,const ll &b){if(a>b)a=b;}
const int maxn = 1010000;

int n,m;
char _name[maxn][15];
int ans[maxn],fa[maxn];

struct edge{int y,nex;}a[maxn<<1]; int len,fir[maxn];
inline void ins(const int x,const int y){a[++len]=(edge){y,fir[x]};fir[x]=len;}
ll d[maxn],val[maxn];
int id[maxn];
inline bool cmp(const int x,const int y){return d[x]<d[y];}

struct node
{
ll x;int i;
friend inline bool operator <(const node x,const node y){return x.x>y.x;}
};
priority_queue<node>q;
ll mn[maxn];
int siz[maxn];
void dfs(const int x)
{
siz[x]=0;
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y)
{
d[y]=d[x]+val[y];
dfs(y);
siz[x]++;
}
if(!siz[x]) q.push((node){val[x],x});
}

void Upd(int tx)
{
mn[tx]+=val[tx];

if(tx==n+1) return;
int x=fa[tx]; siz[x]--;
if(siz[x]) return;

mn[x]=LLONG_MAX;
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y)
down(mn[x],mn[y]);
q.push((node){mn[x]+val[x],x});
}

int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);

for(int i=1;i<=n;i++)
{
scanf("%s",_name[i]);
fa[i]=n+1+y; val[i]=c;
ins(fa[i],i);
}
for(int i=1;i<=m;i++)
{
fa[n+1+i]=n+1+y; val[n+1+i]=c;
ins(fa[n+1+i],n+1+i);
}
dfs(n+1);

for(int i=1;i<=n;i++) id[i]=i;
sort(id+1,id+n+1,cmp);
for(int i=1;i<=n;i++)
{
ll nowt=d[id[i]];
while(!q.empty())
{
const node now=q.top();
if(nowt<now.x) break;
q.pop(); Upd(now.i);
}
ans[id[i]]=q.size();
}

for(int i=1;i<=n;i++) printf("%s %d\n",_name[i],ans[i]+1);

return 0;
}

Problem G Oil

code

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<algorithm>
#define ll long long
#define ld long double
using namespace std;

const int maxn = 2100;
const ld eps = 1e-7;

int Sgn(ld x){ return fabs(x)<eps?0:(x>0?1:-1); }

int n;
struct point
{
ld x,y;
friend inline point operator -(const point &a,const point &b){return (point){a.x-b.x,a.y-b.y};}
inline ld rad(){ return x/y; }
};
struct Line
{
point a,b;
ld val;
}L[maxn];

struct node
{
friend inline bool operator <(const node x,const node y)
{
return Sig<0;
}
}a[maxn<<1]; int cnt;
ld ans;
void Upd(ld now)
{
for(int i=1;i<=cnt;i++)
{
else now-=L[a[i].i].val;
ans=max(ans,now);
}
}

int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);

scanf("%d",&n);
for(int i=1;i<=n;i++)
{
ld l,r,h; scanf("%Lf%Lf%Lf",&l,&r,&h); if(Sgn(l-r)>0) swap(l,r);
L[i]=(Line){(point){l,h},(point){r,h}};
L[i].val=r-l;
ans=max(ans,L[i].val);
}

for(int i=1;i<=n;i++)
{
cnt=0;
for(int j=1;j<=n;j++) if(Sgn(L[i].a.y-L[j].a.y))
{
if(Sgn(r1-r2)>0) swap(r1,r2);
a[++cnt]=(node){j,1,r1};
a[++cnt]=(node){j,-1,r2};
}
sort(a+1,a+cnt+1);
Upd(L[i].val);
}
printf("%.0Lf\n",ans);

return 0;
}

Problem H Polygonal Puzzle

Problem I Road Times

code

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define pb push_back
#define fir first
#define sec second
#define mp make_pair
using namespace std;

const int maxn = 500;
const double eps = 1e-6;
const double inf = 1e20;

vector< pair<int,int> >c[maxn]; int tot;
namespace Simplex
{
int n,m,pn;
int idx[maxn],idy[maxn];
double a[maxn][105];

void init()
{
m=tot;
for(int i=0;i<=m;i++) for(int j=0;j<=n;j++) a[i][j]=0;
for(int i=1;i<=m;i++)
{
a[i][0]=c[i][0].sec;
for(int j=1;j<(int)c[i].size();j++) a[i][c[i][j].fir]=-c[i][j].sec;
}
}
int t[maxn],tp;
void pivot(const int &e,const int &l)
{
double tc=-a[l][e];
for(int i=0;i<=n;i++) if(i!=e) a[l][i]/=tc;
a[l][e]=-1/tc;

tp=0; for(int i=0;i<=n;i++) if(fabs(a[l][i])>eps&&i!=e) t[++tp]=i;

for(int i=0;i<=m;i++) if(i!=l)
{
for(int j=1;j<=tp;j++) a[i][t[j]]+=a[i][e]*a[l][t[j]];
//for(int j=0;j<=n;j++) if(j!=e) a[i][j]+=a[i][e]*a[l][j];
a[i][e]*=a[l][e];
}
swap(idx[e],idy[l]);
++pn;
}
int type;
double ans[maxn];
double simplex()
{
for(int i=1;i<=n;i++) idx[i]=i;
for(int i=1;i<=m;i++) idy[i]=n+i;

int x,y;
while(1)
{
x=y=0;
for(int i=1;i<=m;i++) if(a[i][0]<-eps&&(!y||a[i][0]<a[y][0])) y=i;
if(!y) break;
for(int i=1;i<=n;i++) if(a[y][i]>eps&&(!x||a[y][i]>a[y][x])) x=i;
if(!x) { puts("Infeasible");return 0.0; }
pivot(x,y);
}

while(1)
{
x=y=0;
for(int i=1;i<=n;i++) if(a[0][i]>eps&&(!x||a[0][i]>a[0][x])) { x=i;break; }
if(!x) break;
double temp=inf;
for(int i=1;i<=m;i++) if(a[i][x]<-eps)
{
double cc=-a[i][0]/a[i][x];
if(cc<temp) temp=cc,y=i;
}
if(!y) { puts("Unbounded");return 0.0; }
pivot(x,y);
}

return a[0][0];
//if(!type) return;
//for(int i=1;i<=m;i++) if(idy[i]<=n) ans[idy[i]]=a[i][0];
//for(int i=1;i<=n;i++) printf("%.10lf ",ans[i]);
//putchar('\n');
}
}
int n,r,Q;
int id[40][40],val[40][40],cnt;
int dis[40][40]; vector<int>pat[40][40];
int vis[maxn],S,T;
void Path()
{
scanf("%d%d",&S,&T); S++; T++;
for(int i=1;i<=cnt;i++) vis[i]=0;
for(int i=0;i+1<(int)pat[S][T].size();i++)
vis[id[pat[S][T][i]][pat[S][T][i+1]]]=1;
}

int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);

scanf("%d",&n);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
{
int x; scanf("%d",&x); if(x!=-1&&i!=j)
{
id[i][j]=++cnt;
val[i][j]=x;
dis[i][j]=x;
}
else dis[i][j]=1e9;
}
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
{
pat[i][j].pb(i);
if(j!=i) pat[i][j].pb(j);
}
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) if(i!=k) for(int j=1;j<=n;j++) if(i!=j&&k!=j)
if(dis[i][j]>dis[i][k]+dis[k][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
pat[i][j].clear();
for(int l=0;l<(int)pat[i][k].size();l++) pat[i][j].pb(pat[i][k][l]);
for(int l=1;l<(int)pat[k][j].size();l++) pat[i][j].pb(pat[k][j][l]);
}

Simplex::n=cnt;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(id[i][j])
{
++tot; c[tot].pb(mp(0,-val[i][j])); c[tot].pb(mp(id[i][j],-1));
++tot; c[tot].pb(mp(0,val[i][j]*2)); c[tot].pb(mp(id[i][j],1));
}

scanf("%d",&r);
for(int i=1;i<=r;i++)
{
Path(); int ut; scanf("%d",&ut);
++tot; c[tot].pb(mp(0,-ut));
for(int j=1;j<=cnt;j++) if(vis[j]) c[tot].pb(mp(j,-1));
++tot; c[tot].pb(mp(0,ut));
for(int j=1;j<=cnt;j++) if(vis[j]) c[tot].pb(mp(j,1));
}
//double t3=clock();
//cout << t3 <<endl;

scanf("%d",&Q);
for(int i=1;i<=Q;i++)
{
Path(); printf("%d %d ",S-1,T-1);

Simplex::init();
for(int j=1;j<=cnt;j++) if(vis[j]) Simplex::a[0][j]=-1.0;

printf("%.10lf ",-Simplex::simplex());

Simplex::init();
for(int j=1;j<=cnt;j++) if(vis[j]) Simplex::a[0][j]=1.0;

printf("%.10lf\n",Simplex::simplex());
}
//printf("%d\n",Simplex::pn);
//double t4=clock()-t3;
//cout << t4 << endl;
return 0;
}

Problem J Spin Doctor

A和B的连线会将凸包分成两部分，分界点可以二分出来（A->B和B->2~n的叉积是在分界点前面一段正的，分界点后面是负的）

code

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define ld long double
using namespace std;

inline void read(int &x)
{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
int Sgn(ll x) { return x==0?0:(x>0?1:-1); }
const int maxn = 510000;
const ld eps = 1e-12;

int n,base,Ans;
struct Point
{
ll x,y;
friend inline Point operator +(const Point &a,const Point &b){return (Point){a.x+b.x,a.y+b.y};}
friend inline Point operator -(const Point &a,const Point &b){return (Point){a.x-b.x,a.y-b.y};}
friend inline ll operator *(const Point &a,const Point &b){return a.x*b.y-a.y*b.x;}
friend inline bool operator ==(const Point &a,const Point &b){return a.x==b.x&&a.y==b.y;}
ld Len(){ return sqrt((ld)x*x+(ld)y*y); }
void print(){printf("%lld %lld\n",x,y);}
}a[maxn],b[maxn],zero; int an,bn;
inline bool cmp(const Point &x,const Point &y)
{
ll tc=(x-a[1])*(y-x);
return tc==0?((x-a[1]).Len()<(y-a[1]).Len()):tc>0;
}

Point vst=(Point){0,-1};
struct data
{
Point x; int c;
friend inline bool operator <(const data &x,const data &y){ return x.x*y.x>0; }
}v[maxn]; int vn,now0;

struct Convex_Hull
{
Point c[maxn]; int cn;
void build_convex()
{
for(int i=2;i<=an;i++) if(a[i].y<a[1].y||(a[i].y==a[1].y&&a[i].x<a[1].x))
swap(a[1],a[i]);
for(int i=1;i<=bn;i++) b[i]=b[i]-a[1];
for(int i=2;i<=an;i++) a[i]=a[i]-a[1];
a[1]=(Point){0,0};
sort(a+2,a+an+1,cmp);

cn=0;
for(int i=1;i<=an;i++)
{
while(cn>1&&(c[cn]-c[cn-1])*(a[i]-c[cn])<=0) cn--;
c[++cn]=a[i];
}
while(cn>2&&(c[cn]-c[cn-1])*(c[1]-c[cn])<=0) cn--;
}
void get_convex()
{
build_convex();
if(cn==1) { printf("%d\n",base); exit(0); }
if(cn==2)
{
for(int i=1;i<=bn;i++)
{
if((b[i]-c[cn])*(c[cn]-c[1])==0&&
fabs((b[i]-c[1]).Len()+(b[i]-c[cn]).Len()-(c[1]-c[cn]).Len())<=eps)
Ans++;
}
printf("%d\n",base+Ans);
exit(0);
}
}
bool In_Convex(Point x)
{
if(x.y<0) return false;
if((c[cn]-c[1])*(x-c[cn])>0) return false;
int l=2,r=cn;
while(l<=r)
{
int mid=(l+r)>>1;
if((c[mid]-c[1])*(x-c[mid])<=0) r=mid-1;
else l=mid+1;
}++r;
ll cs=(c[r]-c[r-1])*(x-c[r]);
if(cs==0&&fabs((x-c[r]).Len()+(x-c[r-1]).Len()-(c[r]-c[r-1]).Len())>eps) cs=-1;
return cs>=0;
}
void Add(Point x,Point l,Point r)
{
if((r-x)*(l-r)>0) swap(l,r);
//int sp=0; if(l.x<r.x||(l.x==r.x&&l.y<r.y)) sp=1,swap(l,r);
//x.print();l.print();r.print();
//if(l*l1!=0) puts("qaq");
//if(r*r1!=0) puts("qaq");

//if(sp) swap(l,r);
if(l.x<0) l=zero-l,r=zero-r;

if(r.x>=0)
{
if(l.x!=0) v[++vn]=(data){l,1};
else now0++;
if(r.x!=0) v[++vn]=(data){r,-1};
}
else
{
r=zero-r;
now0++; v[++vn]=(data){r,-1};
v[++vn]=(data){l,1};
}
}
Point Find(Point x,int L,int R)
{
Point re=c[L]-x;
if(L<R)
{
int l,r;
ll tc=(c[1]-x)*(c[L+1]-c[1]);
if(!tc) tc=(c[1]-x)*(c[L]-c[1]);
if(tc<0)
{
for(l=L+1,r=R;l<=r;)
{
int mid=(l+r)>>1;
if((c[mid-1]-x)*(c[mid]-c[mid-1])<=0) l=mid+1;
else r=mid-1;
}l--;
}
else
{
for(l=L+1,r=R;l<=r;)
{
int mid=(l+r)>>1;
if((c[mid-1]-x)*(c[mid]-c[mid-1])>=0) l=mid+1;
else r=mid-1;
}l--;
}
re=c[l]-x;
}
return re;
}
void Query(Point x)
{
if(In_Convex(x)) { base++;return; }

int p1=1,p2,sig=Sgn((c[1]-x)*(c[2]-c[1])),l,r;

for(l=2,r=cn;l<=r;)
{
int mid=(l+r)>>1;
if(Sgn((c[1]-x)*(c[mid]-c[1]))==sig) l=mid+1;
else r=mid-1;
}p2=--l;

}
}ch;

void Solve()
{
for(int i=1;i<=bn;i++) ch.Query(b[i]);
v[++vn]=(data){vst,0};
sort(v+1,v+vn+1);

int now=now0; Ans=now;
for(int i=1;i<=vn;)
{
int j=i+1;for(;j<=vn&&v[i].x*v[j].x==0;j++);j--;
for(;i<=j;i++) now+=v[i].c;
Ans=min(Ans,now);
}
}

int main()
{
//freopen("4617.in","r",stdin);
//freopen("4617.out","w",stdout);

zero=(Point){0,0};

for(int i=1;i<=n;i++)
{
if(c) a[++an]=(Point){x,y};
else b[++bn]=(Point){x,y};
}
base=an;

ch.get_convex();

Solve();
printf("%d\n",Ans+base);

return 0;
}

Problem K String Theory

$k,k-1quotation,k,k,k-1quotation,k$$k,k-1quotation,k,k,k-1quotation,k$

$k-1,k-2qutation,k-1,k,k,k-1,k-2quotation,k-1$$k-1,k-2qutation,k-1,k,k,k-1,k-2quotation,k-1$

code

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 1100;

int n;
int a[maxn],sum[maxn],f[maxn];

int judge(int now)
{
for(int i=1;i<=n;i++) f[i]=a[i];
int l=1,r=n;
for(;now>1&&l<=r;now--)
{
if(f[l]<now) break;
f[l]-=now; if(!f[l]) l++;
if(f[r]<now) break;
f[r]-=now; if(!f[r]) r--;
}
return l<=r&&now==1&&(l==r?f[l]:f[l]+f[r]+sum[r-1]-sum[l])%2==0;
}

int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);

scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
if(sum[n]&1) return puts("no quotation"),0;

for(int i=min(a[1],a[n]);i>=2;i--) if(judge(i))
return printf("%d\n",i),0;
if(sum[n]==2) puts("1");
else puts("no quotation");

return 0;
}

Problem L Swap Space

Problem M What Really Happened on Mars?

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120