2013 Multi-University Training Contest 1

来源:互联网 发布:bugzilla linux 下载 编辑:程序博客网 时间:2024/06/05 22:48

这场比赛。。。伤心了

A - Harvest Moon(HDU4600)

题意:给你好多种种子,每种都有价格和收益。再给你一片地,问你只选一种种子播种的最大收益。

思路:枚举每种种子然后模拟。我很煞笔的开了个数组记录大小为i的土地的数量。TLE到死,最后很猥琐的除GCD,950ms水过。

#include<stdio.h>#include<string.h>#include<stdlib.h>#define maxn 1100#define maxm 11#define Clear(a,b) memset(a,b,sizeof(a))#define LL __int64int gcd(int a,int b)       {    if (b == 0) return a;    else return gcd(b,a%b);}inline LL Max(LL a,LL b){    if (a > b) return a;    return b;}inline LL Min(LL a,LL b){    if (a > b) return b;    return a;}short int rec[maxn][maxm] = {0};void cal_grid(int w,int h,int g[maxm]){    int w3,h3;    g[9] = (w / 3) * (h / 3);    w3 = w % 3;    h3 = h % 3;    g[3 * w3 + 3 * h3 - w3 * h3]++;    g[w3 * 3] += ((h - 3) / 3);    g[h3 * 3] += ((w - 3) / 3);    g[w3 * h3] += 2;    return ;}LL cal_get(int day,int mon,int q,int p,int n,int m,int g[maxm]){    int i,j,rest,num;    LL money = mon;    //day--;    //printf("day:%d\n",day);    //for(i = 1;i <= 9;i++) printf("%d ",g[i]);printf("\n");    //printf("%d %d %d %d",q,p,n,m);    if (m == 0) {        day /= n;        n /= n;        for(i = 0;i <= day;i++){            if (i >= 1)                for(j = 1;j <= 9;j++)                    if (rec[i][j] > 0){                    money += rec[i][j] * j * p;                    g[j] += rec[i][j];                    rec[i][j] = 0;                    }            for(j = 9;j >= 1;j--)                if (g[j] >= 0 && i + n <= day && j * p > q){                    num = Min(money / q,g[j]);                    money -= num * q;                    g[j] -= num;                    rec[i+1][j] += num;                    }                }            }    else {        //printf("\n%dxxx%d\n",i,day);        int GCD = gcd(n,m);        day /= GCD;        n /= GCD;        m /= GCD;        for(i = 0;i <= day;i++){            rest = day - i;            for(j = 9;j >= 1;j--)                if (rec[i][j] > 0) {                    money += rec[i][j] * j * p;                    if (i + m <= day) rec[i+m][j] += rec[i][j];                    rec[i][j] = 0;                    }            //printf("%dxxx%d\n",i,day);            for(j = 9;j >= 1;j--)                if (g[j] > 0) {                    num = Min(money / q,g[j]); //sb了                    if (rest >= n && (((rest - n) / m) * p + p) * j > q) {                        money -= num * q;                        rec[i+n][j] += num;                        g[j] -= num;                        }                    }                }            }    //printf("OK\n");    return money;}int Work(){    int Y,i,j,h,w,A,D,q,p,n,m;    LL ans = 0;    int grid[maxm] = {0},grid2[maxm] = {0};    scanf("%d%d%d%d%d",&w,&h,&A,&D,&Y);    cal_grid(h,w,grid);    //for(i = 1;i <= 9;i++) printf("%d ",grid[i]);printf("\n");    for(i = 1;i <= A;i++) {        scanf("%d%d%d%d",&q,&p,&n,&m);        for(j = 0;j < 10;j++)            grid2[j] = grid[j];        ans = Max(ans,cal_get(D,Y,q,p,n,m,grid2));        }    printf("%I64d\n",ans); //大傻逼    return 0;}int main(){    int Cas;    //freopen("test.in","r",stdin);    //freopen("test.out","w",stdout);    scanf("%d",&Cas);    while(Cas--) Work();    return 0;}


C - Partition(HDU 4602)

这题猥琐的算前几项然后搜的公式

#include<stdio.h>#include<iostream>#include<stdlib.h>#include<string>#include<string.h>#define LL _int64const LL Mod = 1000000007;LL QPow(LL x,LL n){    if (n == 0) return 1;    if (n == 1) return x;    LL tmp = QPow(x,n>>1);    if (n & 1) return (((tmp * tmp) % Mod) * x) % Mod;    else return (tmp * tmp) % Mod;}LL Work(){    LL n,k,dif;    scanf("%I64d%I64d",&n,&k);    dif = n - k;    if (dif < 0) printf("0\n");    else if (dif == 0) printf("1\n");    else if (dif == 1) printf("2\n");    else printf("%I64d\n",(dif+3) * QPow(2,dif-2) % Mod);    return 0;}int main(){    int Cas;    scanf("%d",&Cas);    while(Cas--) Work();    return 0;}
F - Magic Ball Game(HDU 4605)
题意:给你一颗树,想象一个小球从根往下落,问你小球从根到某点的概率。

思路:首先,将路径统计一下,分为左路径和右路径,然后分别统计有多少大于X的。统计我用的傻逼树。

//先分左右,离线保存,两颗傻逼树,DFS#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <set>#include <map>#include <vector>#include <queue>#include <ctime>#pragma comment(linker, "/STACK:32000000")using namespace std;#define LL long long#define Clear(a,b) memset(a,b,sizeof(a))const int N = 300010;const int INF=0x7FFFFFFF;vector<int> O[N];int X[N],ansx[N],ansy[N],son[N][2],w[N];struct SBT{    int key,left,right,size;} Tree_L[N],Tree_R[N];int Root_L,Root_R,top;void left_rot(int &x,SBT tree[]){    int y = tree[x].right;    tree[x].right = tree[y].left;    tree[y].left = x;    tree[y].size = tree[x].size;//转上去的节点数量为先前此处节点的size    tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1;    x = y;}void right_rot(int &x,SBT tree[]){    int y = tree[x].left;    tree[x].left = tree[y].right;    tree[y].right = x;    tree[y].size = tree[x].size;    tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1;    x = y;}void maintain(int &x,bool flag,SBT tree[]){    if(flag == false)//左边    {        if(tree[tree[tree[x].left].left].size > tree[tree[x].right].size)//左孩子的左子树大于右孩子            right_rot(x,tree);        else if(tree[tree[tree[x].left].right].size > tree[tree[x].right].size)//右孩子的右子树大于右孩子        {            left_rot(tree[x].left,tree);            right_rot(x,tree);        }        else return;    }    else //右边    {        if(tree[tree[tree[x].right].right].size > tree[tree[x].left].size)//右孩子的右子树大于左孩子            left_rot(x,tree);        else if(tree[tree[tree[x].right].left].size > tree[tree[x].left].size)//右孩子的左子树大于左孩子        {            right_rot(tree[x].right,tree);            left_rot(x,tree);        }        else return;    }    maintain(tree[x].left,false,tree);    maintain(tree[x].right,true,tree);    maintain(x,true,tree);    maintain(x,false,tree);}/**insert没有合并相同的元素,如果出现相同的元素则把它放到右子树上,这样能保证求第k小数的时候对相同元素也能正确*/bool find(int &x,int key,SBT tree[]){    if (x == 0) return 0;    if (key == tree[x].key) return 1;    if (key < tree[x].key) return find(tree[x].left,key,tree);    else return find(tree[x].right,key,tree);}void insert(int &x,int key,SBT tree[]){    if(x == 0)    {        x = ++top;        tree[x].left = tree[x].right = 0;        tree[x].size = 1;        tree[x].key = key;    }    else    {        tree[x].size ++;        if(key < tree[x].key) insert(tree[x].left,key,tree);        else  insert(tree[x].right,key,tree);//相同元素插入到右子树中        maintain(x, key >= tree[x].key,tree);//每次插入把平衡操作压入栈中    }}int del(int &p,int w,SBT tree[]){    if (tree[p].key==w || (tree[p].left==0 && w<tree[p].key) || (tree[p].right==0 && w>tree[p].key))    {        int delnum=tree[p].key;        if (tree[p].left==0 || tree[p].right==0) p=tree[p].left+tree[p].right;        else tree[p].key=del(tree[p].left,INF,tree);        return delnum;    }    if (w<tree[p].key) return del(tree[p].left,w,tree);    else return del(tree[p].right,w,tree);}int remove(int &x,int key,SBT tree[]){    int d_key;    //if(!x) return 0;    tree[x].size --;    if((key == tree[x].key)||(key < tree[x].key && tree[x].left == 0) ||            (key>tree[x].key && tree[x].right == 0))    {        d_key = tree[x].key;        if(tree[x].left && tree[x].right)        {            tree[x].key = remove(tree[x].left,tree[x].key+1,tree);        }        else        {            x = tree[x].left + tree[x].right;        }    }    else if(key > tree[x].key)        d_key = remove(tree[x].right,key,tree);    else if(key < tree[x].key)        d_key = remove(tree[x].left,key,tree);    return d_key;}int getmin(int root,SBT tree[]){    int x;    for(x = root ; tree[x].left; x = tree[x].left);    return tree[x].key;}int getmax(int root,SBT tree[]){    int x;    for(x = root ; tree[x].right; x = tree[x].right);    return tree[x].key;}int select(int &x,int k,SBT tree[])//求第k小数{    int r = tree[tree[x].left].size + 1;    if(r == k) return tree[x].key;    else if(r < k) return select(tree[x].right,k - r,tree);    else return select(tree[x].left,k,tree);}int rank(int &x,int key,SBT tree[])//求key排第几{    if(key < tree[x].key)        return rank(tree[x].left,key,tree);    else if(key > tree[x].key)        return rank(tree[x].right,key,tree) + tree[tree[x].left].size + 1;    return tree[tree[x].left].size + 1;}int pred(int &x,int y,int key,SBT tree[])//前驱 小于{    if(x == 0) return y;    if(tree[x].key < key)        return pred(tree[x].right,x,key,tree);    else return pred(tree[x].left,y,key,tree);}int succ(int &x,int y,int key,SBT tree[])//后继 大于{    if(x == 0) return y;    if(tree[x].key > key)        return succ(tree[x].left,x,key,tree);    else return succ(tree[x].right,y,key,tree);}void inorder(int &x,SBT tree[]){    if(x==0) return;    else    {        inorder(tree[x].left,tree);        cout<<x<<" "<<tree[x].key<<" "<<" "<<tree[x].size<<" "<<tree[tree[x].left].key<<" "<<tree[tree[x].right].key<<endl;        inorder(tree[x].right,tree);    }}//模板void dfs(int x,int Num_L,int Num_R){    //Cal    int i,t1,t2;    //printf("%d %d yy\n",x,O[x].size());    for(i = 0;i < O[x].size();i++){        int tmp = O[x][i];        //printf("fuck\n");        if (find(Root_L,X[tmp],Tree_L) || find(Root_R,X[tmp],Tree_R)) continue;        //tot = Num_L + Num_R;        //printf("fuck\n");        insert(Root_L,X[tmp],Tree_L);        insert(Root_R,X[tmp],Tree_R);        t1 = rank(Root_L,X[tmp],Tree_L);        t2 = rank(Root_R,X[tmp],Tree_R);        remove(Root_L,X[tmp],Tree_L);        remove(Root_R,X[tmp],Tree_R);        t1--;t2--;        //printf("fuck %d %d %d %d\n",t1,t2,Num_L,Num_R);        ansx[tmp] = t2;        ansy[tmp] = t1 * 3 + (Num_L - t1) + t2 * 3 + (Num_R - t2);        }    //printf("L\n");    //L    if (son[x][0] > 0) {        insert(Root_L,w[x],Tree_L);        dfs(son[x][0],Num_L+1,Num_R);        remove(Root_L,w[x],Tree_L);        }    //printf("R\n");    //R    if (son[x][1] > 0) {        insert(Root_R,w[x],Tree_R);        dfs(son[x][1],Num_L,Num_R+1);        remove(Root_R,w[x],Tree_R);        }    return ;}void Work(){    Root_L = Root_R = top = 0;    int n,m,i,u,a,b;    Clear(son,0);    Clear(ansx,-1);    Clear(ansy,-1);    Clear(w,0);    Clear(X,0);    scanf("%d",&n);    for(i = 1;i <= n;i++) O[i].clear();    for(i = 1;i <= n;i++)         scanf("%d",&w[i]);    scanf("%d",&m);    for(i = 1;i <= m;i++)        scanf("%d%d%d",&u,&a,&b),        son[u][0] = a,        son[u][1] = b;    scanf("%d",&m);    for(i = 1;i <= m;i++)        scanf("%d%d",&u,&X[i]),        O[u].push_back(i);    //printf("xxxx\n");    dfs(1,0,0);    //printf("xxxx\n");    for(i = 1;i <= m;i++)        if (ansx[i] == -1) printf("0\n");        else printf("%d %d\n",ansx[i],ansy[i]);    return ;}int main(){    int cas;   // freopen("test.in","r",stdin);   // freopen("test.out","w",stdout);    scanf("%d",&cas);    while(cas--) Work();    return 0;}

G - Occupy Cities(HDU 4606

  floyd+二分+最小路径覆盖


#include<iostream>#include<string.h>#include<stdio.h>#include<string>#include<math.h>#define oo 1e9#define eps 1e-8#define maxn 500#define maxm 10000using namespace std;struct Point{    int u,v;    Point(){}    Point(double a,double b):u(a),v(b){}    Point operator - (const Point p) {return Point(u-p.u,v-p.v);}}p[maxn],wall[maxn];double ma[maxn][maxn];int map[maxn][maxn],match[maxn],id[maxn];bool vis[maxn];int n,m,PP,T,N,M;int dlcmp(double x) {return x<-eps?-1:x>eps;}double sqr(double x) {return x*x;}double dist(Point a,Point b) {return sqrt(sqr(a.u-b.u)+sqr(a.v-b.v));}double cross(Point a,Point b) {return a.u*b.v-b.u*a.v;}int segment_intersect(Point s1,Point e1,Point s2,Point e2){    if (max(s1.u,e1.u)>min(s2.u,e2.u)&&max(s2.u,e2.u)>min(s1.u,e1.u)&&max(s1.v,e1.v)>min(s2.v,e2.v)&&max(s2.v,e2.v)>min(s1.v,e1.v)&&        dlcmp(cross(e1-s1,s2-s1))*dlcmp(cross(e1-s1,e2-s1))<0&&dlcmp(cross(e2-s2,s1-s2))*dlcmp(cross(e2-s2,e1-s2))<0)        return 1;    else        return 0;}bool NO( int x, int y ){    for ( int i = 1; i <= m; ++i )    {         if ( segment_intersect(p[x],p[y],wall[i],wall[i+m]) ) return 0;    }    return 1;}double makemap(){    for ( int i = 1; i <= N; ++i )        for ( int j = 1; j <= N; ++j )          if ( i != j )  ma[i][j] = oo;          else ma[i][j] = 0;    for ( int i = 1; i <= N; ++i )        for ( int j = 1; j < i; ++j )             if ( NO(i,j) )             {                ma[i][j] =  min(ma[i][j],dist(p[i],p[j]));                ma[j][i] = ma[i][j];             }     for ( int k = 1; k <= N; ++k )         for ( int i = 1; i <= N; ++i )            if ( k != i )                for ( int j = 1; j <= N; ++j )                     if ( i !=j && k != j && ma[i][j] > ma[i][k] + ma[k][j] && ma[i][k] < oo && ma[k][j] < oo )                         ma[i][j] = ma[i][k]+ma[k][j];     double maxx = 0;     for ( int i = 1; i <= n; ++i )         for ( int j = 1; j < i; ++j )             if ( maxx < ma[i][j] ) maxx = ma[i][j];      return maxx;}int find( int x ){    for ( int i = 1; i <= n; ++i )        if ( map[x][i] == 1 && vis[i] == 0 )        {            vis[i] = 1;            if ( match[i] == 0 || find(match[i]) )            {                match[i] = x;                return 1;            }        }        return 0;}bool can( double mid ){    memset(map,0,sizeof(map));    for ( int i = 1; i <= n; ++i )        for ( int j = 1; j <= n; ++j )           if ( id[i] < id[j] &&ma[i][j]-mid <=0 )                map[i][j] = 1;      memset(match,0,sizeof(match));      int res = 0;      for ( int i = 1; i <= n; ++i )      {          memset(vis,0,sizeof(vis));          res += find(i);      }      if ( n - res <= PP ) return 1;      else return 0;}int main(){    int u;        scanf("%d",&T);        while ( T-- )        {                scanf("%d%d%d",&n,&m,&PP);                for ( int i = 1; i <= n; ++i )                    scanf("%d%d",&p[i].u,&p[i].v);                for ( int i = 1; i <= m; ++i )                {                     scanf("%d%d%d%d",&p[i+n].u,&p[i+n].v,&p[i+n+m].u,&p[i+n+m].v);                     wall[i].u = p[i+n].u; wall[i].v = p[i+n].v;                     wall[i+m].u = p[i+n+m].u;  wall[i+m].v=p[i+n+m].v;                }                for ( int i = 1; i <= n; ++i )                {                    scanf("%d",&u); id[u] = i;                }                N = n + m + m;                double r = makemap(),l = 0.0,mid;                while ( (r-l) > eps )                {                     mid = ( r + l ) / 2;                     if ( can(mid) == 1  ) r = mid;                     else l = mid;                }                printf("%.2lf\n",r);        }        return 0;}

H - Park Visit(HDU 4607

  先用两遍DFS求出直径ans,当k小于等于直径时,答案为k-1;否则答案为(k-ans)*2+ans-1
#include<iostream>#include<string.h>#include<string>#include<stdio.h>#define maxn 200000#define maxm 500000using namespace std;int first[maxn],cnt,dep[maxn];struct edd{    int v,next;}e[maxm];void add( int u, int v ){    e[cnt].v = v; e[cnt].next = first[u]; first[u] = cnt++;}void dfs(int u, int fa, int deep ){    dep[u] = deep;    for ( int i = first[u]; i != -1; i = e[i].next )    {        int v = e[i].v;        if ( v != fa ) dfs(v,u,deep+1);    }}int main(){    int T,n,m,u,v;    scanf("%d",&T);    while ( T-- )    {        scanf("%d%d",&n,&m);        memset(first,-1,sizeof(first)); cnt = 0;        for ( int i = 1; i < n; ++i )        {            scanf("%d%d",&u,&v);            add(u,v); add(v,u);        }        memset(dep,0,sizeof(dep));        int res = 1;        dfs(res,0,0);        for ( int i = 2; i <= n; ++i )             if ( dep[i] > dep[res] ) res = i;        dfs(res,0,0);        int ans = 0,k;        for ( int i = 1; i <= n; ++i )            if ( ans < dep[i] ) ans = dep[i];        ans++;        for ( int i = 1; i <= m; ++i )        {            scanf("%d",&k);            if ( k <= ans ) printf("%d\n",k-1);            else printf("%d\n",(k-ans)*2+ans-1);        }    }    return 0;} 

K - Cards(HDU 4610

16种卡片,2^16种情况

#include<iostream>#include<string.h>#include<string>#include<stdio.h>#include<algorithm>#define maxn 5000020#define N 5000010#define mm 50using namespace std;int pp[maxn+10],ge[75536];bool Isp[maxn];int you[mm],dan[50];int n,m,nn,cnt,K,ans;struct pai{    int x,z;}pi[mm];void Prim(){    memset(Isp,0,sizeof(Isp));    cnt = 0;    Isp[1] = 1;    for ( int i = 2; i < N; ++i )        if ( !Isp[i] )            for ( int j = 2; j * i < N; ++j )                Isp[i*j] = 1;     for ( int i = 2; i < N; ++i )         if ( !Isp[i] )            pp[++cnt] = i;}bool conditions1( int x ){    if( !Isp[x] ) return 1;    else return 0;}bool conditions2( int x ){    int gg =1,hh = 0;    for ( int i = 1; pp[i] * pp[i] <= x ; ++i )    {        if ( x % pp[i] == 0  )        {            hh = 0;            while ( x % pp[i] == 0 )            {                ++hh;                x /= pp[i];            }            gg *= ( hh + 1 );        }    }    if ( x != 1 )  gg *= 2;    if ( !Isp[gg] ) return 1;    else return 0;}bool conditions3( int x ){      int gg   = 1, hh = 0,nn;      for ( int i = 1; pp[i] * pp[i] <= x; ++i )      {          if ( x % pp[i] == 0 )          {              hh = pp[i];              nn = 1;              while ( x % pp[i] == 0 )              {                   nn += hh;                   hh *= pp[i];                   x /= pp[i];              }              gg *= nn;          }      }      if( x != 1 ) gg *= ( x+ 1 );      if ( !Isp[gg] ) return 1;      else return 0;}bool conditions4( int x ){     if( x == 1 )        return 1;    int yz[40], cn=-1;    bool flag;    for( int i = 1; pp[i] * pp[i] <= x; i++ )    {        if( x % pp[i] == 0 )        {            int nn = 0;            while( x % pp[i] == 0 )            {                x /= pp[i];                nn++;            }            yz[++cn] = nn;        }    }    if( x != 1 ) yz[++cn] = 1;    for( int i = 0; i <= cn; i++ )    {        if( yz[i] % 4 == 1 || yz[i] % 4 == 2 )        {            flag = 0;            for( int j = 0; j <= cn; j++ )            {                if( j != i && yz[j] % 2 == 1 )                    flag = 1;            }            if( flag == 0 )                return 0;        }    }    return 1;}int cmp( pai p1, pai p2 ){    return p1.z > p2.z;}int main(){    int T;    Prim();    for ( int i = 0; i  < 16; ++i )    {            pi[i].x = i;            pi[i].z = 0;            for ( int j = 0; j < 4; ++j )                if ( i & (1<<j) ) pi[i].z++;             you[i] = pi[i].z;    }    sort(pi,pi+16,cmp);    scanf("%d",&T);    while ( T-- )    {         scanf("%d%d",&n,&K);         memset(ge,0,sizeof(ge));         int now = 0,a = 0, y = 0, x = 0,z = 0;         for  ( int i = 1; i <= n; ++i )         {             scanf("%d%d",&x,&z);             a = 0;    y = 0;             if ( conditions1(x) ) y |= 1;             if ( conditions2(x) ) y |= 2;             if ( conditions3(x) ) y |= 4;             if ( conditions4(x) ) y |= 8;             for ( int j = 0; j < 4; ++j )                 if ( y & 1 << j ) ++a;             if ( i == n ) printf("%d\n",a);             else printf("%d ",a);             ge[y] += z;         }         for ( int i = 0; i < 4 ; ++i )             scanf("%d",&dan[i]);         for ( int i = 0; i < 16; ++i )             if ( ge[i] != 0 ) now |= 1<<i;         ans = -1e9;         for  ( int i = 0; i < ( 1 << 16 ); ++i )         {              int num = 0,res= 0, zhang = 0,gg;              if ( i == ( i & now) )              {                  for ( int j = 0; j < 16; ++j )                      if ( i & (1<<j) )                      {   ++num; res += you[j]; zhang = zhang | j; }                   if ( num > K ) continue;                   for ( int j = 0; j < 16; ++j )                        if ( i & ( 1 << pi[j].x ) )                        {                            gg = ge[pi[j].x];                            --gg;                            gg = min(gg,K-num);                            num += gg;                            res += you[pi[j].x] * gg;                        }                    if ( num != K ) continue;                    for ( int j = 0; j <= 3 ; ++j )                        if ( ( zhang & ( 1 << j ) )== 0 ) res += dan[j];                    ans = max(ans,res);                }         }         printf("%d\n",ans);    }    return 0;}


原创粉丝点击