zoukankan      html  css  js  c++  java
  • [2017.4.7校内训练赛by hzwer]

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    报警啦.......hzwer又出丧题虐人啦.....

    4道ctsc...有一道前几天做过了,一道傻逼哈希还wa了十几次,勉强过了3题..我好菜啊都不会


    A.[ctsc2014][bzoj3555]企鹅QQ

    给定n个长度为l的字符串,两量不同,求有多少对字符串只有一个字符不同。  n<=300000  l<=200

    这个很明显就是哈希啦......我写了几发都随便wa,然后怒而滚键盘才过了.map会T,用了个手写map

    #include<iostream>
    #include<cstdio>
    #include<map>
    #define orz 891172543311LL
    #define mod 10000300000007LL
    #define ditoly 10000002000009LL 
    #define lxh 23333
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
     
    map<ll,int> mp[202];
    int n,l,s,cnt=0;
    ll f[200],g[205];
    ll ans=0;
    char st[205];
    int head[205][lxh];
    struct edge
    {
        int ans;ll x;int next; 
    }e[6000006]; 
     
    void check(int num,ll hash)
    {
        int d=hash%lxh;
        for(int i=head[num][d];i;i=e[i].next)
        if(e[i].x==hash){ans+=e[i].ans;++e[i].ans;return;}
        e[++cnt]=(edge){1,hash,head[num][d]};head[num][d]=cnt;
    }
     
    int main()
    {
        n=read();l=read();s=read();
        if(l<=1) return 0*puts("0");
        for(int i=1;i<=n;i++)
        {
            scanf("%s",st+1);
            for(int j=1;j<=l;j++) f[j]=(1LL*f[j-1]*11119LL+st[j])%orz;
            for(int j=l;j;j--) g[j]=(1LL*g[j+1]*10537LL+st[j])%mod;
            for(int j=1;j<=l;j++)
            {
                ll hash=(1701LL*f[j-1]-107LL*g[j+1])%ditoly;
                check(j,hash);
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }

    B.[ctsc2007][bzoj1150]数据备份
    前几天写的题...可以戳这里 

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define INF 2000000000
    #define MN 100000
    #define pa pair<long long,int>
    #define mp make_pair
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    long long ans=0;
    int n,k,ne[MN+5],la[MN+5],a[MN+5],len[MN+5];
    bool del[MN+5];
    priority_queue<pa,vector<pa>,greater<pa> > q;
    
    int main()
    {
        n=read();k=read();
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=1;i<=n+1;i++)la[i+1]=i,ne[i]=i+1;
        la[1]=0;ne[n+1]=0;
        for(int i=2;i<=n;i++)
            q.push(mp(len[i]=a[i]-a[i-1],i));
        len[1]=len[n+1]=INF;
        for(int i=1;i<=k;i++)
        {
            while(del[q.top().second])q.pop();
            ans+=q.top().first;int x=q.top().second;q.pop();
            int a=la[x],b=ne[x];
            del[a]=del[b]=1;
            q.push(mp(len[x]=len[a]+len[b]-len[x],x));
            la[x]=la[a];ne[x]=ne[b];
            ne[la[a]]=x;la[ne[b]]=x;
        }
        cout<<ans;
        return 0;
    }

    C.[Ctsc2015][bzoj4055]misc
    题目好长啊...戳这里看题目

    题解:我们用f[i][j]表示i到j的最短路径的宽度和,题目即求 $$ans[j]=sum_{i ot=j ot=k}frac{ai*ak*f(i,j)*f(j,k)}{f(i,k)}$$

    整理一下得到    $$ans[j]=sum_{i ot=j ot=k}ai*f(i,j)*frac{ak*f(j,k)}{f(i,k)}$$

    枚举点i,dij/spfa得到它的最短路括扑图,然后枚举点j,发现后面那一坨东西可以dp,令$g(x)={f(j,k)*ak/f(i,k)}$这家伙的转移可以通过乘以转移的那条边的宽度得到,所以这道题就做完了

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<cmath>
    #define MN 1000
    #define INF 2000000000000000000LL 
    #define ld long double
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int qx[MN+5][MN+5],top[MN+5],tail;
    ld h[MN+5];
    ld dis[MN+5][MN+5],ans[MN+5],f[MN+5][MN+5];
    ld g[MN+5];
    struct edge{int to,next;ld b,c;}e[8005];
    int n,m,cnt=0,head[MN+5],a[MN+5],in[MN+5][MN+5];
    
    void ins(int f,int t,ld B,ld C)
    {
        e[++cnt]=(edge){t,head[f],B,C};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],B,C};head[t]=cnt;
    }
    queue<int> q;
    void spfa(int from)
    {
        for(int i=1;i<=n;i++)dis[from][i]=INF;
        dis[from][from]=0;
        q.push(from);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].next)
            {
                ld d=dis[from][u]+e[i].b;
                if(d<dis[from][e[i].to]) dis[from][e[i].to]=d,q.push(e[i].to);
            }
        }
    }
    
    void work(int from)
    {
        qx[from][top[from]=1]=from;tail=0;
        f[from][from]=1;
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=e[j].next)
                if(dis[from][i]+e[j].b==dis[from][e[j].to])
                    in[from][e[j].to]++;
        for(int i=1;i<=n;i++)
            if(!in[from][i]) q.push(i);
        while(top[from]>tail)
        {
            int u=qx[from][++tail];
            for(int j=head[u];j;j=e[j].next)
                if(dis[from][u]+e[j].b==dis[from][e[j].to]) 
                {
                    if(!--in[from][e[j].to]) qx[from][++top[from]]=e[j].to;
                    f[from][e[j].to]+=f[from][u]*e[j].c;    
                }    
        } 
    }
    
    void dp(int from)
    {
        memset(h,0,sizeof(h));
        for(int j=top[from];j>1;j--)
        {
            int x=qx[from][j];
            for(int i=head[x];i;i=e[i].next)
                if(dis[from][x]+e[i].b==dis[from][e[i].to])
                {
                    int v=e[i].to;
                    h[x]+=e[i].c*h[v];
                }
            ans[x]+=(ld)a[from]*f[from][x]*h[x];
            h[x]+=(ld)a[x]/f[from][x];
        }    
    }
    
    int main()
    {
        n=read();m=read();double B,C;
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read();scanf("%lf%lf",&B,&C);
            ins(x,y,(ld)B,(ld)C);
        }
        for(int i=1;i<=n;i++) 
            spfa(i),work(i),dp(i);
        for(int i=1;i<=n;i++)
            printf("%.8lf
    ",(double)ans[i]);
        return 0;
    }

    D.[ctsc2015][bzoj4067]gender

    题面实在是太神了,根本没法解释,戳这里

    这道题貌似会保证k条链都是并排的?问了善良的黄学长他说忘了qaq......标程没有处理,假装就是这样吧

    题解:看到了那个计算答案的式子,发现$lfloor ln(1+A) floor$根本没法拆,但是k和n很小,A最大200,所以考虑暴力枚举它。

    然后我们发现每一层其实都是独立的,也就是说我们可以把一层压到一起。同一层的答案我们考虑枚举状态,用最小割来计算。每个点与S连边表示改,与T连边表示不改,然后类似文理分科那样每个配对建出两个点分别和S,T相连,跑一遍最小割就能得出来。

    所以我们得到了所有层所有状态的答案,接下来就可以状压dp了,f[i][j][k]表示前i层有j个不同,最后一层状态是k的最大获利,这个很好转移,最后更新答案。

    然后发现对于同一个$lfloor ln(1+A) floor$,最小割的结果相同,只需要枚举一下A就行了    题目时限很宽,复杂度不好计算,就算是O(能过)呗。

    (其实你可以发现用男女或者换不换都能表示状态,也就是说给定的初始性别可以是根本没用的)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define INF 2000000000
    #define ll long long
    #define S 0
    #define T 1001
    #define MN 25000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int fa[T+5],n,k,m,p,bel[T+5],d[MN],q[MN],head[MN],cnt,top,c[MN],C[T+5],ln[T+5],old[T+5];
    struct edge{int to,next,w;}e[T*T+5];
    struct pair{int u,v,s;double d;}s[10005];
    char st[MN];
    ll g[61][18],f[61][205][18],ans;
    
    inline int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
    
    void ins(int f,int t,int w)
    {
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0};head[t]=cnt;
    }
    
    int dfs(int x,int f)
    {
        if(x==T)return f;
        int used=0;
        for(int&i=c[x];i;i=e[i].next)
            if(e[i].w&&d[e[i].to]==d[x]+1)
            {
                int w=dfs(e[i].to,min(f-used,e[i].w));
                used+=w;e[i].w-=w;e[i^1].w+=w;
                if(used==f)return used;
            }
        return d[x]=-1,used;
    }
    
    bool bfs()
    {
        memset(d,0,sizeof(d));int i,j;
        for(d[q[top=i=1]=S]=1;i<=top;i++)
            for(j=c[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to])
                    d[q[++top]=e[j].to]=d[q[i]]+1;
        return d[T];
    }
    
    void solve(int A,int t,int now)
    {
        memset(head,0,sizeof(head));cnt=1;ll sum=0;
        for(int i=1;i<=m;i++)
            if(old[i]==t)
            {
                if(bel[i])
                {
                    if((now&(1<<bel[i]-1))>0)
                        ins(S,i,INF),sum-=C[i];
                    else ins(i,T,INF);
                }
                else
                    ins(i,T,C[i]);
            }
        int id=T+1;
        for(int i=1;i<=p;i++)
            if(old[s[i].u]==t&&old[s[i].v]==t)
            {
                int c1=A*s[i].s,c2=A*(int)(s[i].s*s[i].d);
                sum+=c1+c2;
                ++id;ins(id,T,c1);
                ins(s[i].u,id,INF);ins(s[i].v,id,INF);
                ++id;ins(S,id,c2);
                ins(id,s[i].u,INF);ins(id,s[i].v,INF);
            }
        while(bfs()) sum-=dfs(S,INF);
        g[t][now]=sum;
    }
    
    int calc(int x,int y)
    {
        int sum=0;
        for(int j=1;j<(1<<k);j<<=1)
            if((x&j)!=(y&j)) ++sum;
        return sum;
    }
    
    void dp(int l)
    {
        for(int i=1;i<=n;i++)
            for(int j=0;j<=l;j++)
                for(int x=0;x<1<<k;x++)
                    f[i][j][x]=-INF;
        for(int i=0;i<(1<<k);++i)
            f[1][0][i]=max(f[1][0][i],g[1][i]);
        for(int i=1;i<=n;++i)
            for(int j=0;j<=l;++j)
                for(int x=0;x<(1<<k);++x)if(f[i][j][x]!=-INF)
                    for(int y=0;y<(1<<k);++y)
                    {
                        int now=calc(x,y)+j;
                        f[i+1][now][y]=max(f[i+1][now][y],f[i][j][x]+g[i+1][y]);
                    }
    }
    
    int main()
    {
        n=read();k=read();m=read();p=read();
        scanf("%s",st+1);
        for(int i=1;i<=m;i++) C[i]=read();
        for(int i=1;i<=k;i++)
            for(int j=1;j<=n;j++)
            {
                int x=read();
                bel[x]=i;old[x]=j;
            }
        for(int i=1;i<=m;i++) fa[i]=i;
        for(int i=1;i<=p;i++)
        {
            s[i].u=read();s[i].v=read();
            s[i].s=read();scanf("%lf",&s[i].d);
            fa[getfa(s[i].u)]=getfa(s[i].v);
        }
        for(int i=1;i<=m;i++)if(old[i]) old[getfa(i)]=old[i];
        for(int i=1;i<=m;i++)old[i]=old[getfa(i)];
        for(int i=1;i<=m;i++)if(!old[i]) old[i]=1;
        for(int i=0;i<=200;i++) ln[i]=(int)(log(i+1)*10);
        for(int i=1;i<=n*k;i++)
        {
            if(ln[i]!=ln[i-1])
            {
                for(int j=1;j<=n;j++)
                    for(int K=0;K<(1<<k);K++)
                        solve(ln[i],j,K);
                dp(i);
            }
            for(int j=0;j<(1<<k);j++) ans=max(ans,f[n][i][j]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Learn Goroutine
    Redis eviction policies
    Hungarian Algorithm
    Prime and Factors
    HDU 2642 Stars
    236. Lowest Common Ancestor of a Binary Tree
    Leetcode 96. Unique Binary Search Trees
    Search in Rotated Sorted Array
    ID Generator
    概率问题
  • 原文地址:https://www.cnblogs.com/FallDream/p/hzwer47.html
Copyright © 2011-2022 走看看