# NOIP2016提高组复赛 解题报告

## Day1

### T1

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 100005

int n,m,d,num,now;
char s[N][20];
int len[N],dir[N],pre[N],nxt[N];

int main()
{
freopen("toy.in","r",stdin);
freopen("toy.out","w",stdout);
scanf("%d%d\n",&n,&m);
for (int i=1;i<=n;++i)
{
gets(s[i]);len[i]=strlen(s[i]);
dir[i]=s[i][0]-'0';
for (int j=1;j<len[i]-1;++j) s[i][j]=s[i][j+1];
}
/*
for (int i=1;i<=n;++i)
{
for (int j=1;j<=len[i]-2;++j) putchar(s[i][j]);
putchar('\n');
}
*/
now=1;
for (int i=1;i<=m;++i)
{
scanf("%d%d",&d,&num);
if (!d)//left
{
if (!dir[now])//in
{
now=((now-num-1)%n+n)%n+1;
}
else//out
{
now=(now+num-1)%n+1;
}
}
else//right
{
if (!dir[now])
{
now=(now+num-1)%n+1;
}
else
{
now=((now-num-1)%n+n)%n+1;
}
}
}
for (int i=1;i<=len[now]-2;++i)
putchar(s[now][i]);
putchar('\n');
}

### T2

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 1000005
#define base 300000
#define sz 19

int n,m,x,y,s,t,r,ct,ft;
struct hp{int pt,t,val;}tor[N*2],fromr[N*2];
int tot,point[N],nxt[N*2],v[N*2];
int father[N],a[N],w[N],dfs_clock,f[N][sz+5],h[N],in[N],ans[N];

{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
void build(int x,int fa)
{
father[x]=fa;h[x]=h[fa]+1;in[x]=++dfs_clock;
for (int i=1;i<sz;++i)
{
if (h[x]-(1<<i)<1) break;
f[x][i]=f[f[x][i-1]][i-1];
}
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa)
{
f[v[i]][0]=x;
build(v[i],x);
}
}
int lca(int x,int y)
{
if (h[x]<h[y]) swap(x,y);
int k=h[x]-h[y];
for (int i=0;i<sz;++i)
if (k&(1<<i)) x=f[x][i];
if (x==y) return x;
for (int i=sz-1;i>=0;--i)
if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
int cmp(hp a,hp b)
{
return in[a.pt]<in[b.pt];
}
void dfs_to(int x,int fa)
{
int val=w[x]+h[x],minus=a[val];
while (ct<=2*m&&tor[ct].pt==x) a[tor[ct].t+h[tor[ct].pt]]+=tor[ct].val,ct++;
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa)
dfs_to(v[i],x);
ans[x]+=a[val]-minus;
}
void dfs_from(int x,int fa)
{
int val=w[x]-h[x]+1,minus=a[val+base];
while (ft<=2*m&&fromr[ft].pt==x)
a[fromr[ft].t+base]+=fromr[ft].val,ft++;
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa)
dfs_from(v[i],x);
ans[x]+=a[val+base]-minus;
}
int main()
{
freopen("running.in","r",stdin);
freopen("running.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
}
build(1,0);
for (int i=1;i<=n;++i) scanf("%d",&w[i]);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&s,&t);
r=lca(s,t);
tor[++ct].pt=s,tor[ct].t=0,tor[ct].val=1;
if(r!=1)tor[++ct].pt=father[r],tor[ct].t=h[s]-h[r]+1,tor[ct].val=-1;
fromr[++ft].pt=t,fromr[ft].t=h[s]-h[r]-(h[r]-1),fromr[ft].val=1;
fromr[++ft].pt=r,fromr[ft].t=h[s]-h[r]-(h[r]-1),fromr[ft].val=-1;
}
sort(tor+1,tor+ct+1,cmp);ct=1;
sort(fromr+1,fromr+ft+1,cmp);ft=1;
dfs_to(1,0);
memset(a,0,sizeof(a));dfs_from(1,0);
for (int i=1;i<=n;++i)
{
if (i!=1) putchar(' ');
printf("%d",ans[i]);
}
}

### T3

f(i,j,0/1)$f(i,j,0/1)$表示前i$i$个课程，一共选了j$j$个申请，第i$i$个0不申请1申请的最小期望。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 2005

int n,m,v,e,x,y;
int c[N],d[N];
double z,inf,kk[N],sdis[N],dis[N][N],f[N][N][2],ans;

void floyed()
{
for (int k=1;k<=v;++k)
for (int i=1;i<=v;++i)
for (int j=1;j<=v;++j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int main()
{
freopen("classroom.in","r",stdin);
freopen("classroom.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&v,&e);
for (int i=1;i<=n;++i) scanf("%d",&c[i]);
for (int i=1;i<=n;++i) scanf("%d",&d[i]);
for (int i=1;i<=n;++i) scanf("%lf",&kk[i]);
memset(dis,127,sizeof(dis));inf=dis[0][0];
for (int i=1;i<=v;++i) dis[i][i]=0.0;
for (int i=1;i<=e;++i)
{
scanf("%d%d%lf",&x,&y,&z);
dis[x][y]=dis[y][x]=min(dis[x][y],z);
}
floyed();memset(f,127,sizeof(f));
/*
for (int i=1;i<=v;++i)
for (int j=i;j<=v;++j)
printf("%d %d %.2lf\n",i,j,dis[i][j]);
puts("");
*/
for (int i=2;i<=n;++i)
ans+=dis[c[i-1]][c[i]];
f[1][0][0]=f[1][1][1]=0.0;
for (int i=1;i<n;++i)
for (int j=0;j<=min(i,m);++j)
{
if (f[i][j][0]!=inf)
{
f[i+1][j][0]=min(f[i+1][j][0],f[i][j][0]+dis[c[i]][c[i+1]]);
if (j<m) f[i+1][j+1][1]=min(f[i+1][j+1][1],f[i][j][0]+dis[c[i]][c[i+1]]*(1-kk[i+1])+dis[c[i]][d[i+1]]*kk[i+1]);
}
if (f[i][j][1]!=inf)
{
f[i+1][j][0]=min(f[i+1][j][0],f[i][j][1]+dis[c[i]][c[i+1]]*(1-kk[i])+dis[d[i]][c[i+1]]*kk[i]);
if (j<m) f[i+1][j+1][1]=min(f[i+1][j+1][1],f[i][j][1]+(1-kk[i])*(1-kk[i+1])*dis[c[i]][c[i+1]]+(1-kk[i])*kk[i+1]*dis[c[i]][d[i+1]]+kk[i]*(1-kk[i+1])*dis[d[i]][c[i+1]]+kk[i]*kk[i+1]*dis[d[i]][d[i+1]]);
}
}
for (int i=0;i<=m;++i) ans=min(ans,min(f[n][i][0],f[n][i][1]));
printf("%0.2lf\n",ans);
}

## Day2

### T1

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long

int t,n,m,k,ANS;
int prime[9]={0,2,3,5,7,11,13,17,19};
int p[2005][20],s[2005][20],a[20],b[20],c[20],d[20],ans[2005][2005],Ans[2005][2005];

void calc(int x)
{
int now=x;if (now==1) return;
for (int i=1;i<=8;++i)
if (now%prime[i]==0)
{
while (now%prime[i]==0)
p[x][i]++,now/=prime[i];
if (now==1) break;
}
}
void sum(int x)
{
for (int i=1;i<=8;++i)
s[x][i]=s[x-1][i]+p[x][i];
}
int main()
{
freopen("problem.in","r",stdin);
freopen("problem.out","w",stdout);
scanf("%d%d",&t,&k);
for (int i=1;i<=2000;++i)
calc(i);
for (int i=1;i<=2000;++i) sum(i);
for (n=0;n<=2000;++n)
{
bool flag=true;
for (int i=1;i<=8;++i) a[i]=s[n][i],b[i]=s[n][i],c[i]=0,d[i]=a[i]-b[i]-c[i]-p[k][i];
for (int i=1;i<=8;++i)
{
if (d[i]<0) {flag=false;break;}
}
if (flag) ans[n][0]++;
for (m=1;m<=n;++m)
{
bool flag=true;
for (int i=1;i<=8;++i) b[i]-=p[n-m+1][i],c[i]+=p[m][i],d[i]=a[i]-b[i]-c[i]-p[k][i];
for (int i=1;i<=8;++i)
{
if (d[i]<0) {flag=false;break;}
}
if (flag) ans[n][m]++;
}
}
for (int i=0;i<=2000;++i) Ans[i][0]=ans[i][0],Ans[0][i]=ans[0][i];
for (int i=1;i<=2000;++i)
for (int j=1;j<=2000;++j) Ans[i][j]=Ans[i-1][j]+Ans[i][j-1]-Ans[i-1][j-1]+ans[i][j];
while (t--)
{
scanf("%d%d",&n,&m);
printf("%d\n",Ans[n][m]);
}
return 0;
}

### T2

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
#define inf 2100000000
#define N 100005

double u,v,p;
int q[4][N*100],l[4],r[4];

int cmp(int a,int b)
{
return a>b;
}
int Max()
{
int a=-inf,b=-inf,c=-inf,ans=1;
if (l[1]<r[1]) a=q[1][l[1]];
if (l[2]<r[2]) b=q[2][l[2]];
if (l[3]<r[3]) c=q[3][l[3]];
if (a<b) a=b,ans=2;
if (a<c) a=c,ans=3;
return ans;
}
int main()
{
freopen("earthworm.in","r",stdin);
freopen("earthworm.out","w",stdout);
scanf("%d%d%d%lf%lf%d",&n,&m,&qaq,&u,&v,&t);p=u/v;
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
sort(a+1,a+n+1,cmp);
for (int i=1;i<=n;++i) q[1][r[1]++]=a[i];
for (int i=1;i<=m;++i)
{
int k=Max();
if (i%t==0)
{
if (i>t) putchar(' ');
printf("%d",now);
}
int nxt1=floor(p*(double)now),nxt2=now-floor(p*(double)now);
}
putchar('\n');
for (int i=1;i<=n+m;++i)
{
int k=Max();
if (i%t==0)
{
if (i>t) putchar(' ');
printf("%d",now);
}
}
}

### T3

f(i)$f(i)$表示打掉的点状态为i$i$的时候最少用的小鸟数。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 18

const double eps=1e-9;
int T,n,m;
double a,b,x[N+1],y[N+1];
int birds[N+1][N+1],f[1<<N];

void clear()
{
n=m=0;
a=b=0.0;
memset(x,0,sizeof(x));memset(y,0,sizeof(y));
memset(birds,0,sizeof(birds));memset(f,0,sizeof(f));
}
int dcmp(double x)
{
if (x<=eps&&x>-eps) return 0;
if (x>eps) return 1;
return -1;
}
void calc(double &a,double &b,int id,int jd)
{
a=b=0;
double A=x[id],B=y[id],C=x[jd],D=y[jd];
if (dcmp(A-C)==0) return;
a=(B*C-A*D)/(A*A*C-A*C*C);
b=(B*C*C-D*A*A)/(A*C*C-A*A*C);
}
bool on(int id,double a,double b)
{
double A=x[id],B=y[id];
if (dcmp(A*A*a+A*b-B)==0) return true;
else return false;
}
void init()
{
for (int i=1;i<=n;++i)
for (int j=i+1;j<=n;++j)
{
calc(a,b,i,j);
if (a>=0) continue;
for (int k=1;k<=n;++k)
if (on(k,a,b)) birds[i][j]|=1<<(k-1);
}
}
int main()
{
freopen("angrybirds.in","r",stdin);
freopen("angrybirds.out","w",stdout);
scanf("%d",&T);
while (T--)
{
clear();
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%lf%lf",&x[i],&y[i]);
init();
memset(f,127,sizeof(f));
f[0]=0;
for (int i=0;i<1<<n;++i)
{
for (int j=1;j<=n;++j)
if ((i&(1<<(j-1)))==0)
{
for (int k=j+1;k<=n;++k)
if ((i&(1<<(k-1)))==0)
f[i|birds[j][k]]=min(f[i|birds[j][k]],f[i]+1);
f[i|(1<<(j-1))]=min(f[i|(1<<(j-1))],f[i]+1);
break;
}
}
printf("%d\n",f[(1<<n)-1]);
}
}