zoukankan      html  css  js  c++  java
  • 洛谷 NOIP提高组模拟赛 Day1

    传送门

    ## $T1$

    一道结论题,设原来A队能力最大的是x,那么A队的选择方案就是$2^{x-1}$,B队的选择方案就是$(2^{n-x}-1)$种,因为不能不选。其中$1leq xleq n$,那么根据乘法原理,最后的答案就是 $sumlimits^{n-1}_{x=1}2^{x-1}*(2^{n-x}-1)$,化简可得 $ans=n*2^{n-1}-(2^{n}-1)$,然后一个快速幂就行了。


    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define int long long
    
    using namespace std;
    const int mod = 1e9+7;
    typedef long long LL;
    
    int n;
    
    int fast_pow(int x,int y){
        int ret=1;
        for(;y;y>>=1){
            if(y&1) ret=(LL)ret*x%mod;
            x=(LL)x*x%mod;
        }
        return ret;
    }
    
    signed main(){
        scanf("%lld",&n);
        int ans=(n*fast_pow(2,n-1)%mod-(fast_pow(2,n)-1)%mod+mod)%mod;
        cout<<ans<<endl;
        return 0;
    }
    View Code




    ## $T2$

    一道比较套路的题吧,首先肯定是先按每个物品的消失时间排序,然后就可以跑背包了,$f[i][j]$表示到了第$i$个物品,时间为$j$的最大收益,时间复杂度$O(n*MAX\_D)$。输出方案考试时候想了挺久。。。其实就是倒着走回去。


    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    const int MAXN = 105;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int n,ans,lx,ly,all[MAXN],cnt;
    int f[MAXN][2005];
    
    struct Node{
        int t,w,d,id;
    }data[MAXN];
    
    inline bool cmp(Node A,Node B){
        return A.d<B.d;
    }
    
    int main(){
    //    freopen("T2.out","w",stdout);
        n=rd();
        for(int i=1;i<=n;i++)
            data[i].t=rd(),data[i].d=rd(),data[i].w=rd(),data[i].id=i;
        sort(data+1,data+1+n,cmp);
        for(int i=1;i<=n;i++)
            for(int j=0;j<data[i].d;j++){
                f[i][j]=f[i-1][j];
                if(j>=data[i].t)
                     f[i][j]=max(f[i][j],f[i-1][j-data[i].t]+data[i].w);
            }
        for(int i=0;i<=data[n].d;i++)
            if(f[n][i]>ans) {
                ans=f[n][i];
                ly=i;
            }
        lx=n;cout<<ans<<endl;
        for(int i=n;i;i--)
            for(int j=ly;j>=0;j--)
                if(f[i][j]==ans) {
                    if(f[i-1][j]!=f[i][j]) ans-=data[i].w,all[++cnt]=data[i].id;
                    ly=j;break;
                }
        printf("%d
    ",cnt);
        for(int i=cnt;i;i--) printf("%d ",all[i]); 
        return 0;
    }
    View Code




    ## $T3$

    考试的时候没有做出来,后来经过$G color{red} {hostCai}$神犇的指点,才知道用网络流做,开一个超级源点$S$和一个超级汇点$T$,然后将每个点拆成左部点和右部点,$S$向左部点连流量为$a[i]$的点,表示每个点至多能向其他点给出$a[i]$的能量,左部点向能到达的右部点连流量为$inf$的边(注意要连自己),右部点向汇点连流量为$b[i]$的边,表示最多收到$b[i]$的能量,然后跑一个最大流,看所有右部点到汇点的边是否满流,不满说明无解。再看每个左部点到所有右部点的反边的流量即为答案。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #define czq namespace 
    
    using czq std;
    const int MAXN = 205;
    const int MAXM = 2005;
    const int inf = 0x3f3f3f3f;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int n,m,head[MAXN],to[MAXM],val[MAXM],nxt[MAXM];
    int cnt=1,a[MAXN],b[MAXN],S,T,cur[MAXN],d[MAXN],ans[MAXN][MAXN];
    queue<int> Q;
    
    inline void add(int bg,int ed,int w){
        to[++cnt]=ed,nxt[cnt]=head[bg],val[cnt]=w,head[bg]=cnt;
        to[++cnt]=bg,nxt[cnt]=head[ed],val[cnt]=0,head[ed]=cnt;
    }
    
    bool bfs(){
        memset(d,0,sizeof(d));
        while(Q.size()) Q.pop();
        Q.push(S);d[S]=1;
        while(Q.size()){
            int x=Q.front();Q.pop();
            for(register int i=head[x];i;i=nxt[i]){
                int u=to[i];
                if(!d[u] && val[i]){
                    d[u]=d[x]+1;
                    if(u==T) return true;
                    Q.push(u);
                }            
            }
        }
        return false;
    }
    
    int dinic(int x,int flow){
        if(x==T) return flow;
        int res=flow,k;
        for(register int &i=cur[x];i && res;i=nxt[i]){
            int u=to[i];
            if(val[i] && d[u]==d[x]+1){
                k=dinic(u,min(res,val[i]));
                if(!k) d[u]=0;
                val[i]-=k;res-=k;val[i^1]+=k;
    //            cout<<k<<endl;
            }
        }
        return flow-res;
    }
    
    int main(){
        n=rd(),m=rd();int x,y;S=2*n+1,T=2*n+2;
        for(int i=1;i<=n;i++) a[i]=rd(),add(S,i,a[i]),add(i,i+n,inf);
        for(int i=1;i<=n;i++) b[i]=rd(),add(i+n,T,b[i]);
        for(int i=1;i<=m;i++){
            x=rd(),y=rd();
            add(x,y+n,inf);
            add(y,x+n,inf);
        }
        while(bfs()) {memcpy(cur,head,sizeof(head));dinic(S,inf);}
        for(register int i=head[T];i;i=nxt[i])
            if(val[i^1]) {puts("NO");return 0;}
        puts("YES");
        for(register int i=1;i<=n;i++)
            for(register int j=head[i];j;j=nxt[j]){
                int u=to[j];
                ans[i][u-n]+=val[j^1];
            }
        for(register int i=1;i<=n;i++){
            for(register int j=1;j<=n;j++)
                printf("%d ",ans[i][j]);
            putchar('
    ');
        }
        return 0;
    }
    View Code
  • 相关阅读:
    android 6.0 以上在doze模式精确定时
    MySQL 性能优化神器 Explain 使用分析
    android java层通过jni加载使用第三方的so库
    android 抓取native层奔溃
    mybatis面试入门
    Python实现异步 io多种方式
    可用率map处理
    雷哥带你走进Javascript
    前端存储技术
    听雷哥浅谈Redis
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9745559.html
Copyright © 2011-2022 走看看