浙大 4月月赛

来源:互联网 发布:宠物白狐淘宝价格 编辑:程序博客网 时间:2024/04/30 12:48
zoj3929

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;#define N 100005const int MOD=1000000007;typedef long long ll;int two[N];int pos[N];int tree[N];int n;inline int lowbit(int x){    return x&(-x);}void add(int x,int y){    for(int i=x;i<=n;i+=lowbit(i)){        tree[i]+=y;        if(tree[i]>=MOD) tree[i]-=MOD;    }}int sum(int x){    int an=0;    for(int i=x;i>=1;i-=lowbit(i)){        an+=tree[i];        if(an>=MOD) an-=MOD;    }    return an;}int main(){    int T;    int i,j,k;    scanf("%d",&T);    two[0]=1; for(i=1;i<=100000;i++) two[i]=(two[i-1]*2)%MOD;    while(T--){        ll ans=0;        scanf("%d",&n);        memset(tree,0,sizeof(tree));        for(i=1;i<=n;i++) scanf("%d",&pos[i]);        for(i=1;i<=n;i++){            ans=( ans+(ll)( sum(n)-sum(pos[i])+MOD )*two[n-i] )%MOD;            ans=( ans+(ll)( sum(pos[i]-1) )*two[n-i] )%MOD;            if(i==1) add(pos[i],2);            else add(pos[i],two[i-1]);        }        printf("%lld\n",ans);    }    return 0;}/*【题意】    一个双端队列 依次将带标号的球等概率从左或右放入    求 xi > xi+1 的i的数量 的方案数【做法】    树状数组维护    每次加上该球    1.从左边进入 恰好它旁边的球比它小的方案数    2.从右边进入 恰好它旁边的球比它大的方案数【思考】*/

zoj3930

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;#define INF 0x3f3f3f3fconst int MOD =1000000007;typedef long long ll;char t[2005];char a[2005];vector<char> vc;int cn;int main(){    int T;    int i,j,k;    int cn;    scanf("%d",&T); getchar();    while(T--){        vc.clear();        gets(t); int len=strlen(t);        for(i=0;i<len;i++){            if( t[i]==' ' || t[i]=='\t' ) continue;            else if( t[i]>='0' && t[i]<='9' ) vc.push_back(t[i]);            else if(t[i]=='d'){                for(cn=0,j=i+1;j<len;j++){                    if( t[j]>='0' && t[j]<='9' ) a[cn++]=t[j];                    else break;                }                a[cn]='\0';                i=j-1;                ll tmp=0;                for(j=0;j<vc.size();j++){                    tmp=tmp*10+vc[j]-'0';                } vc.clear();                if(tmp<=1) {                    printf("[d%s]",a);                }else {                    printf("(");                    while(tmp--){                        printf("[d%s]",a);                        if(tmp) printf(" + ");                    }                    printf(")");                }            }else if( t[i]=='+' || t[i]=='*' || t[i]=='-' || t[i]=='/' ){                for(j=0;j<vc.size();j++) printf("%c",vc[j]); vc.clear();                printf(" %c ",t[i]);            }else {                for(j=0;j<vc.size();j++) printf("%c",vc[j]); vc.clear();                printf("%c",t[i]);            }        }        for(j=0;j<vc.size();j++) printf("%c",vc[j]); vc.clear();        printf(" = [Result]\n");    }    return 0;}/*【题意】    将一段字符串进行处理    1.删去空格和tab键('\t') 坑点    2.将3d5转换为[d5] + [d5] + [d5]    3.在运算符两边加上空格【做法】    模拟 注意'\t'坑点【思考】    比赛时应该耐心看完每个题 这个题之前没人做 最后才被人发现是水题*/


zoj3931

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<map>#include<queue>using namespace std;typedef long long ll;int S;int F[150];map<ll,int> mp[2];map<ll,int>::iterator it;priority_queue<int,vector<int>,greater<int> >Q;struct Node{    ll l,r;}tree[150];int main(){    int T;    int i,j,k;    ll target;    scanf("%d",&T);    while(T--){        while(!Q.empty()) Q.pop();        for(i=0;i<2;i++) mp[i].clear();        scanf("%d",&S);        for(i=0;i<S;i++) scanf("%d",&F[i]);        scanf("%lld",&target);        for(i=0;i<S;i++) {            Q.push(F[i]);        }        int cn1=0;        while(Q.size()>1){            int t1=Q.top(); Q.pop();            int t2=Q.top(); Q.pop();            Q.push(t1+t2);            tree[++cn1].l=t1; tree[cn1].r=t2;        }        int flag=1;        mp[flag][tree[1].l]=1; mp[flag][tree[1].r]=1;        for(i=2;i<=cn1;i++){            mp[flag^1].clear();            for(it=mp[flag].begin();it!=mp[flag].end();it++){                ll t1=it->first;                if( t1+tree[i].l<=target ) mp[flag^1][t1+tree[i].l]=1;                if( t1+tree[i].r<=target ) mp[flag^1][t1+tree[i].r]=1;            }            flag^=1;        }        if(mp[flag][target]) printf("Yes\n");        else printf("No\n");    }    return 0;}、/*【题意】    对于给出的序列进行哈夫曼建树    求是否有方案树满足  每个数的编码中 0 的个数合为 E【做法】    模拟【思考】    这个题当时也是没时间看 全卡在那道zkw费用流上了*/

zoj3933

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;const int MAXN=505;const int MAXM=250005;const int INF=0x3f3f3f3f;struct Edge{    int to,next,cap,flow,cost;    Edge(int _to=0,int _next=0,int _cap=0,int _flow=0,int _cost=0):        to(_to),next(_next),cap(_cap),flow(_flow),cost(_cost){}}edge[MAXM];vector<pair<int,int> > vc;struct ZKW_MinCostMaxFlow{    int head[MAXN],tot;    int cur[MAXN];    int dis[MAXN];    bool vis[MAXN];    int ss,tt,N;    int min_cost,max_flow;    void init(){        tot=0;        vc.clear();        memset(head,-1,sizeof(head));    }    void addedge(int u,int v,int cap,int cost){        edge[tot]=Edge(v,head[u],cap,0,cost);        head[u]=tot++;        edge[tot]=Edge(u,head[v],0,0,-cost);        head[v]=tot++;    }    int aug(int u,int flow){        if(u==tt) return flow;        vis[u]=true;        for(int i=cur[u];i!=-1;i=edge[i].next){            int v=edge[i].to;            if( edge[i].cap>edge[i].flow && !vis[v] && dis[u]==dis[v]+edge[i].cost ){                int tmp=aug(v,min(flow,edge[i].cap-edge[i].flow));                edge[i].flow+=tmp;                edge[i^1].flow-=tmp;                cur[u]=i;                if(tmp) return tmp;            }        }        return 0;    }    bool modify_label(){        int d=INF;        for(int u=0;u<N;u++){            if(vis[u])            for(int i=head[u];i!=-1;i=edge[i].next){                int v=edge[i].to;                if(edge[i].cap>edge[i].flow && !vis[v])                    d=min(d,dis[v]+edge[i].cost-dis[u]);            }        }        if(d==INF) return false;            for(int i=0;i<N;i++)            if(vis[i]){                vis[i]=false;                dis[i]+=d;            }        return true;    }    void mincostmaxflow(int start,int ed,int n){        ss=start,tt=ed,N=n;        min_cost=max_flow=0;        for(int i=0;i<n;i++) dis[i]=0;        while(1){            for(int i=0;i<n;i++) cur[i]=head[i];            while(1){                for(int i=0;i<n;i++) vis[i]=false;                int tmp=aug(ss,INF);                if(tmp==0) break;                max_flow+=tmp;                min_cost+=tmp*dis[ss];            }            if(!modify_label()) break;        }        printf("%d %d\n",max_flow,2*max_flow-min_cost);    }    void prin(int x,int y){        int i,j;        for(i=1;i<=x;i++){            for(j=head[i];j!=-1;j=edge[j].next){                if(edge[j].flow==1){                   vc.push_back(make_pair(i,edge[j].to)); break;                }            }        }    }}solve;char s1[505];char s2[505];int num[505];int pre[505];int bad[505][505];int main(){    int T;    int n;    int i,j,k;    scanf("%d",&T);    while(T--){        solve.init();        memset(bad,0,sizeof(bad));        int a1=0; int a2=0;        scanf("%d %s %s",&n,&s1,&s2);        for(i=0;s1[i];i++){            if(s1[i]=='1') a1++;            else a2++;        }        int b1=0; int b2=a1;        for(i=0;s1[i];i++){            if(s1[i]=='1') num[i]=++b1,pre[b1]=i;            else num[i]=++b2,pre[b2]=i;        }        for(i=0;i<n;i++){            int a,b; scanf("%d",&a);            for(j=0;j<a;j++){                scanf("%d",&b); bad[i][b-1]=1;            }        }        for(i=0;i<n;i++)        for(j=i+1;j<n;j++){            if(bad[i][j]==0){                int t1=num[i]; int t2=num[j];                if(s1[i]==s1[j]) continue;                if(t1>t2) swap(t1,t2);                solve.addedge( t1,t2,1,(s2[i]=='1')+(s2[j]=='1') );            }        }        for(i=1;i<=a1;i++) solve.addedge(0,i,1,0);        for(i=a1+1;i<=n;i++) solve.addedge(i,n+1,1,0);        solve.mincostmaxflow(0,n+1,n+2);        solve.prin(a1,n);        for(i=0;i<vc.size();i++){            int t1=vc[i].first; int t2=vc[i].second;            printf("%d %d\n",pre[t1]+1,pre[t2]+1);        }    }    return 0;}/*【题意】    有两组人 给出他们的性别和各自不喜欢的人    要求从两组各选出一个人成为一队    求最多能组成的队数 以及最多的女生的情况【做法】    zkw费用流 用KM以及SPFA被卡的不要不要的    两组放两边 二分建图【思考】*/


0 0
原创粉丝点击