• NOI 2012


    [NOI2012]随机数生成器

    矩阵乘法,要注意两数相乘时,可能会爆long long,用快速乘。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    long long mod1,a,c,x,n,mod2;
    
    long long mul(long long p,long long b)
    {
        long long res=0;
        for(;b;b>>=1)
        {
            if(b&1) res=(res+p)%mod1;
            p=(p+p)%mod1;
        }
        return res;
    }
    
    struct Matrix
    {
        long long a[10][10];
        Matrix(){memset(a,0,sizeof(a));}
        Matrix operator * (const Matrix &aa)
        {
            Matrix c;
            for(int i=1;i<=9;i++)
                for(int j=1;j<=9;j++)
                    for(int p=1;p<=9;p++)
                        c.a[i][j]=(c.a[i][j]%mod1+mul((a[i][p]%mod1),(aa.a[p][j]%mod1))%mod1)%mod1;
            return c;
        }
    };
    
    Matrix Pow(Matrix p,long long b)
    {
        Matrix res;
        for(int i=1;i<=3;i++) res.a[i][i]=1LL;
        for(;b;b>>=1)
        {
            if(b&1) res=res*p;
            p=p*p;
        }
        return res;
    }
    
    int main()
    {
        scanf("%lld%lld%lld%lld%lld%lld",&mod1,&a,&c,&x,&n,&mod2);
        Matrix trans,ini;
        trans.a[1][1]=0,trans.a[1][2]=0,trans.a[1][3]=0;
        trans.a[2][1]=1,trans.a[2][2]=a%mod1,trans.a[2][3]=0;
        trans.a[3][1]=0,trans.a[3][2]=1,trans.a[3][3]=1;
        ini.a[1][1]=0,ini.a[1][2]=x,ini.a[1][3]=c%mod1;
        Matrix ans=ini*Pow(trans,n);
        printf("%lld",(ans.a[1][2]%mod2+mod2)%mod2);
        return 0;
    }

    [NOI2012]美食节

    本来应该这样建图,把每个厨师拆成sigma_p个点,分别表示倒数第i次做菜的该位厨师j,向每个菜品p连边。

    但是这样会TLE,我们不妨模拟一下MCMF的过程,对于每个厨师来说,首先SPFA出来的代价最小的通路肯定是最后一次做某菜,因为等待的时间短。我们不妨先建所有的倒数第一个点,哪个满流了就建倒数第二个点,很好的模拟了增广的过程,剪掉了许多不必要的边。

    CODE:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxm=1e7+10;
    const int maxn=1e5+10;
    #define idd(i,j) ((i-1)*sum+j+n)
    #define left(x) ((x-n-1)/sum+1)
    #define right(x) ((x-n-1)%sum+1)
    struct point
    {
        int to,nxt;
        int cap,cost;
    }edge[maxm];
    int n,m,Mincost,Maxflow,tot,S,T,sum;
    int head[maxn],p[maxn],flow[maxn],vis[maxn],id[maxn],pre[maxn],dis[maxn];
    int ti[120][120];
    
    inline void add(int u,int v,int c,int f)
    {
        edge[tot]=(point){v,head[u],c,f};
        head[u]=tot++;
        edge[tot]=(point){u,head[v],0,-f};
        head[v]=tot++;
    }
    
    inline bool Bfs()
    {
        queue<int> q;
        memset(dis,-1,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis[S]=0; flow[S]=1e9; vis[S]=1;
        q.push(S);
        while(!q.empty())
        {
            int tt=q.front();
            q.pop();
            vis[tt]=0;
            for(int i=head[tt];~i;i=edge[i].nxt)    
            {
                int v=edge[i].to;
                if(edge[i].cap && (dis[v]==-1 || dis[v]>dis[tt]+edge[i].cost))
                {
                    dis[v]=dis[tt]+edge[i].cost;
                    flow[v]=min(edge[i].cap,flow[tt]);
                    id[v]=i; pre[v]=tt;
                    if(!vis[v]) vis[v]=1,q.push(v);
                }
            }
        }    
        return dis[T]!=-1;
    }
    
    inline void Mcmf()
    {
        while(Bfs())
        {
            int tmp=T,ad=0;
            while(tmp!=S)
            {
                edge[id[tmp]].cap-=flow[T];
                edge[id[tmp]^1].cap+=flow[T];
                tmp=pre[tmp];
            }
            Mincost+=flow[T]*dis[T];
            ad=pre[T]+1;
            add(ad,T,1,0);
            for(int i=1;i<=n;i++)
                add(i,ad,1,ti[i][left(ad)]*right(ad));
        }
    }
    
    int main()
    {
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&p[i]),sum+=p[i];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&ti[i][j]);
        S=0,T=sum*m+n+1;
        for(int i=1;i<=n;i++) add(S,i,p[i],0);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                add(i,idd(j,1),1,ti[i][j]);
        for(int i=1;i<=m;i++)
            add(idd(i,1),T,1,0);
        Mcmf();
        printf("%d",Mincost);
        return 0;
    }
    

      

    [NOI2012]迷失游乐园

    当只有树的时候很套路,up[x]表示从节点x向上走的期望长度,down[x]表示从节点x向下走的期望长度。

    当是基环树的时候,先算down[x],每棵树的树根的up[x]要注意一下,左右全部跑一遍,对于每个环内的点都有可能继续走或下到树里面。

    CODE:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=1e5+10;
    struct point
    {
        int to;
        int nxt;
        double w;
    }edge[maxn*2];
    int n,m,tot,cnt,flag;
    double up[maxn],down[maxn],w_fa[maxn],W[33][33];
    int hav[maxn],nson[maxn],head[maxn],nn[33],in[maxn],vis[maxn],hash[maxn];
    int fath[maxn],pre[maxn],nex[maxn];
     
    inline void add(int u,int v,double w)
    {
        tot++;
        edge[tot].nxt=head[u];
        edge[tot].to=v;
        edge[tot].w=w;
        head[u]=tot;
    }
     
    inline void dfs1(int x,int fa)
    {
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(vis[v] || v==fa) continue;
            nson[x]++,w_fa[v]=edge[i].w;
            hav[v]=1;
            dfs1(v,x);
            down[x]+=down[v]+(double)edge[i].w;
        }
        if(nson[x]) down[x]/=(double)nson[x];
    }
     
    inline void dfs2(int x,int fa)
    {
        if(fa)
        {
            if(nson[fa]-1+hav[fa]>0)
                up[x]=(double)(down[fa]*nson[fa]-w_fa[x]-down[x]+hav[fa]*up[fa])/(double)(nson[fa]-1+hav[fa]);
            up[x]+=(double)w_fa[x];
        }
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(vis[v] || v==fa) continue;
            dfs2(v,x);
        }
    }
     
    inline void Tree_solve()
    {
        dfs1(1,0);
        dfs2(1,0);
    }
     
    inline void get_cir(int x,int fa)
    {
        vis[x]=1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==fa) continue;
            if(vis[v]){flag=v; return;}
            get_cir(v,x);
            if(flag>0){if(flag==x) flag=-1; return;}
            if(flag==-1) break;
        }
        vis[x]=0;
    }
     
    void find_cir(int x, int f)
    {
        if(hash[x]) return;
        nn[++cnt] = x;
        hash[x] = cnt;
        hav[x]=2;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if (v == f) continue;
            if (!vis[v]) continue;
            pre[v] = x; nex[x] = v;
            find_cir(v, x);
            W[hash[x]][hash[v]] = W[hash[v]][hash[x]] = edge[i].w;
            break;
        }
    }
     
    inline void Cir_Tree_solve()
    {
        for(int i=1;i<=n;i++) if(vis[i])
        {
            find_cir(i,0);
            break;   
        }
        double nowp;
        memset(w_fa,0,sizeof(w_fa));
        for(int i=1;i<=cnt;i++) dfs1(nn[i],0);
        for (int i=1;i<=cnt;i++)
        {
            double k=1.0;
            int u=nn[i];
            for(int j=nex[u];j!=u;j=nex[j])
            {
                if(nex[j]!=u) up[u]+=(double)k*((down[j]*nson[j])/(double)(nson[j]+1)+W[hash[pre[j]]][hash[j]]);
                else up[u]+=k*(down[j]+W[hash[pre[j]]][hash[j]]);
                k/=(nson[j]+1);
            }
            k=1.0;
            for(int j=pre[u];j!=u;j=pre[j])
            {
                if(pre[j]!=u) up[u]+=(double)k*((down[j]*nson[j])/(double)(nson[j]+1)+W[hash[nex[j]]][hash[j]]);
                else up[u]+=k*(down[j]+W[hash[nex[j]]][hash[j]]);
                k/=(nson[j]+1);
            }
            up[u]/=2.0;
        }
        for(int i=1;i<=cnt;i++) dfs2(nn[i],0);
    }
     
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            double w;
            scanf("%d%d%lf",&u,&v,&w);
            add(u,v,w),add(v,u,w);
        }
        get_cir(1,0);
        if(m<=n-1) Tree_solve();
        else Cir_Tree_solve();
        double ans=0.0;
        for(int i=1;i<=n;i++)
            ans=ans+(up[i]*hav[i]+down[i]*nson[i])/(double)(nson[i]+hav[i]);
        ans/=(double)n;
        printf("%.5lf",ans);
        return 0;
    }
    

      

    [NOI2012]骑行川藏

    讲的很清楚。

    CODE:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define eps 1e-12
    const int maxn=1e4+10;
    const int inf=1e9;
    int n;
    double E,s[maxn],k[maxn],v[maxn],x[maxn];
    
    inline double cal(double lam)
    {
        double tmp=0;
        for(int i=1;i<=n;i++)
        {
            double l=max(0.0,v[i]),r=inf;
            while(l+eps<r)
            {
                double mid=(l+r)*0.5;
                if(2*lam*k[i]*mid*mid*(mid-v[i])>1)
                    r=mid;
                else l=mid;
            }
            x[i]=(l+r)*0.5;
            tmp+=k[i]*(x[i]-v[i])*(x[i]-v[i])*s[i];
        }
        return tmp;
    }
    
    int main()
    {
        scanf("%d%lf",&n,&E);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf",&s[i],&k[i],&v[i]);
        double l=0,r=inf;
        while(l+eps<r)
        {
            double mid=(l+r)*0.5;
            if(cal(mid)>=E) l=mid;
            else r=mid;
        }
        double ans=0;
        for(int i=1;i<=n;i++)
            ans+=s[i]/x[i];
        printf("%.10lf",ans);
        return 0;
    }
    

      

     

  • 相关阅读:
    百度搜索API v3版本与soap
    Yii整合ZF2及soap实例
    Getting started writing ZF2 modules
    js写出php中的函数系列
    一些有用的命令
    a标签至于flash之上的时候,IE浏览器无法点击连接的问题
    js问题集锦
    php常用函数集锦[备份用的]
    用过的一些js函数[备份用的]
    ELK
  • 原文地址:https://www.cnblogs.com/linda-fcj/p/9131599.html
Copyright © 2020-2023  润新知