2012金华网络赛赛后【缺ABC】

A Mines (HDU 4400)

B Battery (HDU 4401)

C Magic Board (HDU 4402)

D A very hard Aoshu problem (HDU 4403)


枚举“=”的位置,分别对左右两部分进行DFS,统计出相等的个数即可:
 #include<map>
 #include<cstdio>
 #include<cstring>
 using namespace std;
 map<int,int>mp;
 char s[100];
 int len,ans;
 void dfs(int pre,int tmp,int l,int r,bool fg)
 {
     if(l==r)
     {
         if(fg) ans+=mp[pre+tmp];
         else mp[pre+tmp]++;
         return;
     }
     dfs(pre+tmp,s[l]-48,l+1,r,fg);
     dfs(pre,tmp*10+s[l]-48,l+1,r,fg);
 }
 int main()
 {
     while(scanf("%s",s),strcmp(s,"END"))
     {
         len=strlen(s),ans=0;
         for(int i=1;i<len;i++)
         {
             mp.clear();
             dfs(0,0,0,i,0);
             dfs(0,0,i,len,1);
         }
         printf("%d\n",ans/4);
     }
     return 0;
 }


E Worms (HDU 4404)


计算几何,多边形与圆交模板题
 #include<cmath>
 #include<vector>
 #include<cstdio>
 #include<algorithm>
 using namespace std;
 #define sqr(x) ((x)*(x))
 
 const int N=1010;
 const double pi=acos(-1.0);
 
 int n;
 double r;
 
 struct cpoint
 {
     double x,y;
     cpoint(){}
     cpoint(double x,double y):x(x),y(y){}
 }pin[N];
 
 int dcmp(double x){return (x>1e-8)-(x<-1e-8);}
 
 void cal(cpoint u,cpoint v,double r,vector<cpoint>&ret)
 {
     ret.push_back(u);
     double a=sqr(v.x-u.x)+sqr(v.y-u.y);
     double b=2*((v.x-u.x)*u.x+(v.y-u.y)*u.y);
     double c=sqr(u.x)+sqr(u.y)-r*r;
     double d=b*b-4*a*c;
     if(d<0) return;
     d=sqrt(d);
     double t1=(-b+d)/(2*a),t2=(-b-d)/(2*a);
     if(t1>t2) swap(t1,t2);
     if(dcmp(t1)>0&&dcmp(1-t1)>0)
         ret.push_back(cpoint(u.x+(v.x-u.x)*t1,u.y+(v.y-u.y)*t1));
     if(dcmp(t2)>0&&dcmp(1-t2)>0&&dcmp(t2-t1)>0)
         ret.push_back(cpoint(u.x+(v.x-u.x)*t2,u.y+(v.y-u.y)*t2));
 }
 
 double tri(const cpoint &u,const cpoint &v){return u.x*v.y-u.y*v.x;}
 
 double arc(const cpoint &u,const cpoint &v,double r)
 {
     double t=atan2(v.y,v.x)-atan2(u.y,u.x);
     while(t> pi) t-=2*pi;
     while(t<-pi) t+=2*pi;
     return r*r*t;
 }
 
 double area(double r,cpoint pin[],int n)
 {
     double ans=0;pin[n]=pin[0];
     vector<cpoint>v;
     for(int i=0;i<n;i++) cal(pin[i],pin[i+1],r,v);
     v.push_back(v.front());
     for(int i=1;i<v.size();i++)
     {
         if(sqrt(sqr((v[i-1].x+v[i].x)/2)+sqr((v[i-1].y+v[i].y)/2))<r) ans+=tri(v[i-1],v[i]);
         else ans+=arc(v[i-1],v[i],r);
     }
     return fabs(ans/2);
 }
 
 int main()
 {
     double x,y,v,e,t,g,r;
     while(scanf("%lf%lf%lf%lf%lf%lf%lf",&x,&y,&v,&e,&t,&g,&r),dcmp(x+y+v+e+t+g+r))
     {
         scanf("%d",&n);
         x+=v*cos(e/180*pi)*t;
         y+=v*sin(e/180*pi)*t-g*t*t/2;
         for(int i=0;i<n;i++)
         {
             scanf("%lf%lf",&pin[i].x,&pin[i].y);
             pin[i].x-=x,pin[i].y-=y;
         }
         printf("%.2f\n",area(r,pin,n));
     }
     return 0;
 }

F Aeroplane chess (HDU 4405)


。。。
 #include<cstdio>
 #include<cstring>
 
 const int N=100010;
 
 double dp[N];
 int nxt[N];
 
 int main()
 {
     int n,m,u,v;
     while(scanf("%d%d",&n,&m),n||m)
     {
         memset(dp,0,sizeof(dp));
         memset(nxt,-1,sizeof(nxt));
         for(int i=0;i<m;i++) scanf("%d%d",&u,&v),nxt[u]=v;
         for(int i=n-1;i>=0;i--) for(int j=1;j<=6;j++)
         {
             int k=i+j;
             while(~nxt[k]) k=nxt[k];
             dp[i]+=(dp[k]+1)/6;
         }
         printf("%.4f\n",dp[0]);
     }
     return 0;
 }

G GPA (HDU 4406)


最大费用最大流。s到每门课连一条边(k,0),每门课与每天之间按01矩阵连边,每门课与t之间建边:x<60,建(60-x,lim),k+=60-x,x~100,分别建一条(1,g(x+1)-g(x))的边。统计出g(x0)之和+最大费用-k*lim即为最终gpa.
#include<cstdio>
#include<cstring>

typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3fll;
const int N=110,M=100010;
#define min(a,b) ((a)<(b)?(a):(b))

struct MaxCostMaxFlow
{
    int e,ev[M],nxt[M],head[M];
    ll cost[M],dis[M],cap[M];
    int pnt[N],road[N],q[N],bg,ed;
    bool vis[N];
    void init(){e=0;memset(head,-1,sizeof(head));}
    void add(int u,int v,ll f,ll c)
    {
        ev[e]=v;cap[e]=f;cost[e]= c;nxt[e]=head[u];head[u]=e++;
        ev[e]=u;cap[e]=0;cost[e]=-c;nxt[e]=head[v];head[v]=e++;
    }
    bool spfa(int s,int t,int n)
    {
        for(int i=0;i<n;i++) dis[i]=-1,vis[i]=0;
        bg=ed=dis[s]=0;
        pnt[s]=s;q[ed++]=s;
        while(bg!=ed)
        {
            int u=q[bg++];vis[u]=0;
            if(bg==n) bg=0;
            for(int i=head[u];~i;i=nxt[i])
            {
                if(cap[i]<=0)continue;
                ll v=ev[i];
                if(dis[v]<dis[u]+cost[i])
                {
                    dis[v]=dis[u]+cost[i];
                    pnt[v]=u;road[v]=i;
                    if(!vis[v]) q[ed++]=v;
                    vis[v]=1;
                    if(ed==n) ed=0;
                }
            }
        }
        return dis[t]!=-1;
    }
    ll maxcost(int s,int t,int n)
    {
        ll c=0,f=0;
        while(spfa(s,t,n))
        {
            ll minf=inf;
            for(int u=t;u!=s;u=pnt[u]) minf=min(minf,cap[road[u]]);
            for(int u=t;u!=s;u=pnt[u]) cap[road[u]]-=minf,cap[road[u]^1]+=minf;
            f+=minf;
            c+=minf*dis[t];
        }
        return c;
    }
}mc;

int p(ll x){return x>=60?6400-3*(100-x)*(100-x):0;}

int a[50],b[50],c[50][50];
int main()
{
    int n,k,m;
    while(scanf("%d%d%d",&n,&k,&m),n||k||m)
    {
        mc.init();ll cnt=0,sum=0,ans=0;
        for(int i=1;i<=m;i++) scanf("%d",a+i),sum+=a[i];
        for(int i=1;i<=m;i++) scanf("%d",b+i);
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&c[i][j]);

        for(int i=1;i<=n;i++) mc.add(i+m,n+m+1,k,0);
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(c[i][j]) mc.add(j,i+m,k,0);
        for(int i=1;i<=m;i++)
        {
            if(b[i]<60)  cnt+=60-b[i],mc.add(0,i,60-b[i],0xffffffll),b[i]=60;
            ans+=a[i]*p(b[i]);
            for(int j=b[i];j<100;j++) mc.add(0,i,1,a[i]*(p(j+1)-p(j)));
        }
        ans+=mc.maxcost(0,n+m+1,n+m+2)-0xffffffll*cnt;
        printf("%.6f\n",ans>0?ans/1600.0/sum:0);
    }
    return 0;
}


H Sum (HDU 4407)

若g(n)为容斥处理出不与(1,n)中不与p互斥的数之和,则对(l,r)区间ans(l,r)=sum(l,r)-(g(r)-g(l)),修改的数字直接保存下来特判一下。 快哭了赛后才知道初始一定是1-n的 哭
 #include<map>
 #include<cstdio>
 using namespace std;
 
 typedef long long ll;
 const int N=400010;
 int p[N][10],num[N];
 
 int gcd(int a,int b){return b?gcd(b,a%b):a;}
 int cal(int x,int p){return gcd(x,p)>1?0:x;}
 ll g(int n,int p){ll t=n/p; return t*(t+1)/2*p;}
 
 ll dfs(int idx,int b,int now)
 {
     ll ans=0;
     for(int i=idx;i<num[now];i++) ans+=g(b,p[now][i])-p[now][i]*dfs(i+1,b/p[now][i],now);
     return ans;
 }
 
 int main()
 {
     for(int i=2;i<N;i++) if(num[i]==0) for(int j=i;j<N;j+=i) p[j][num[j]++]=i;
     int t,n,q;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d%d",&n,&q);
         map<int,int>c;
         while(q--)
         {
             int op,x,y,p;
             scanf("%d%d%d",&op,&x,&y);
             if(op==1)
             {
                 scanf("%d",&p);
                 ll ans=ll(x+y)*(y-x+1)/2-dfs(0,y,p)+dfs(0,x-1,p);
                 map<int,int>::iterator it,st=c.lower_bound(x),ed=c.upper_bound(y);
                 for(it=st;it!=ed;it++) ans+=cal(it->second,p)-cal(it->first,p);
                 printf("%I64d\n",ans);
             }
             else c[x]=y;
         }
     }
     return 0;
 }

I Minimum Spanning Tree (HDU 4408)

最小生成树计数,模板太长,不贴。

J Family Name List (HDU 4409)


代码太不精简了,3700B 抓狂
 #include<cstdio>
 #include<cstring>
 #include<vector>
 #include<string>
 #include<algorithm>
 #include<map>
 using namespace std;
 const int N=30030;
 const int M=N*2;
 const int H=20;
 string ss[N];
 struct graph
 {
     int e,head[N];
     int ev[M],nxt[M];
     void init()
     {
         e=0;
         memset(head,-1,sizeof(head));
     }
     void addedge(int u,int v)
     {
         ev[e]=v;
         nxt[e]=head[u];
         head[u]=e++;
         ev[e]=u;
         nxt[e]=head[v];
         head[v]=e++;
     }
 }g;
 
 int ln[N];
 struct LCA
 {
     int pnt[N][H],depth[N],stk[N];
     void init()
     {
         ln[0]=ln[1]=0;
         for(int i=2;i<N;i++) ln[i]=ln[i>>1]+1;
     }
     int getfather(int x,int len)
     {
         while(len>0)
         {
             x=pnt[x][ln[len]];
             len-=1<<ln[len];
         }return x;
     }
     int lca(int x,int y)
     {
         int low=0,high=min(depth[x],depth[y]);
         x=getfather(x,depth[x]-high);
         y=getfather(y,depth[y]-high);
         if(x==y) return x;
         while(high-low>1)
         {
             int mid=ln[high-low-1];
             int nx=pnt[x][mid];
             int ny=pnt[y][mid];
             mid=high-(1<<mid);
             if(nx==ny) low=mid;
             else {high=mid;x=nx;y=ny;}
         }
         return pnt[x][ln[high-low]];
     }
     void build(const graph &g,int root,int n)
     {
         for(int i=0;i<n;i++)
         {
             depth[i]=-1;
             memset(pnt[i],-1,sizeof(pnt[i]));
         }
         int top=1;
         depth[stk[0]=root]=0;
         while(top)
         {
             int u=stk[--top];
             for(int i=g.head[u];~i;i=g.nxt[i])
             {
                 int v=g.ev[i];
                 if(depth[v]!=-1) continue;
                 stk[top++]=v;
                 pnt[v][0]=u;
                 depth[v]=depth[u]+1;
             }
         }
         for(int i=1;i<H;i++)
         {
             for(int u=0;u<n;u++) if(pnt[u][i-1]!=-1) pnt[u][i]=pnt[pnt[u][i-1]][i-1];
         }
     }
 }lca;
 bool cmp(int a,int b)
 {
     return ss[a]<ss[b];
 }
 void dfs(int u,int p)
 {
     printf("%s\n",ss[u].c_str());
     vector<int>son;
     for(int i=g.head[u];i!=-1;i=g.nxt[i])
     {
         if(p==g.ev[i]) continue;
         son.push_back(g.ev[i]);
     }
     sort(son.begin(),son.end(),cmp);
     for(int i=0;i<son.size();i++) dfs(son[i],u);
 }
 char s[100],s2[100],op[2];
 int id[N],cnt[N],fa[N];
 int main()
 {
     int n,m;
     //freopen("in.txt","r",stdin);
     lca.init();
     while(scanf("%d",&n),n)
     {
         g.init();
         memset(cnt,0,sizeof(cnt));
         map<string,int>ms;
         scanf("%s",s);
         ss[ms[s]=0]=s;
         for(int i=1; i<n; i++)
         {
             scanf("%s",s);
             ss[i]=s;
             int k=0;
             for(int j=0; s[j]=='.'; j++) k++;
             g.addedge(id[k-1],i);
             ms[s+k]=id[k]=i;
             cnt[id[k-1]]++;
             fa[i]=id[k-1];
         }
         scanf("%d",&m);
         lca.build(g,0,n);
         for(int i=0;i<m;i++)
         {
             scanf("%s",op);
             if(op[0]=='L') dfs(0,0);
             else if(op[0]=='b')
             {
                 scanf("%s",s);
                 int id=ms[s];
                 printf("%d\n",cnt[fa[id]]);
             }
             else
             {
                 scanf("%s%s",s,s2);
                 int id=lca.lca(ms[s],ms[s2]);
                 if(id==ms[s]||id==ms[s2]) id=fa[id];
                 string s=ss[id];
                 int k=0;
                 for(int i=0;s[i]=='.';i++) k++;
                 printf("%s\n",s.c_str()+k);
             }
         }
     }
     return 0;
 }



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值