zoukankan      html  css  js  c++  java
  • 学大伟业 2017 国庆 Day1

     期望得分:100+100+20=220

    实际得分:100+100+20=220

    (好久没有期望==实际了 ,~(≧▽≦)/~)

    对于 a。。。。。。。。a

    如果 第1个a 后面出现的第1个b~z 是右端点,且在第2个a之前,那么有贡献

    如果 第2个a 前面出现的第1个b~z 是左端点,且在第1个a之后,那么有贡献

    最后的贡献/2

    #include<cstdio>
    #include<cstring>
    
    #define N 100001
     
    using namespace std;
    
    char s[N];
    
    int LAST[26],last[N],pre[N][26],suf[N][26];
    bool w[N],c[26];
     
    int main()
    {
        freopen("cross.in","r",stdin);
        freopen("cross.out","w",stdout);
        scanf("%s",s+1);
        int len=strlen(s+1),ans=0,ch;
        
        for(int i=1;i<=len;i++)
            for(int j=0;j<26;j++)
                if(s[i]-'a'==j) pre[i][j]=i;
                else pre[i][j]=pre[i-1][j];
        
        for(int i=0;i<26;i++) suf[len][i]=len+1;
        suf[len][s[len]-'a']=len;
        for(int i=len-1;i;i--)
            for(int j=0;j<26;j++)
                if(s[i]-'a'==j) suf[i][j]=i;
                else suf[i][j]=suf[i+1][j];
        
        for(int i=1;i<=len;i++)
        {
            ch=s[i]-'a';
            c[ch]^=1; w[i]=!c[ch];
            if(c[ch]) LAST[ch]=i;
            else last[i]=LAST[ch];
        }
        
        for(int i=1;i<=len;i++)
            if(w[i])
            {
                for(int j=0;j<26;j++)
                    if(j!=s[i]-'a')
                    {
                        if(suf[last[i]][j]<i && w[suf[last[i]][j]]) ans++;
                        if(pre[i][j]>last[i] && !w[pre[i][j]]) ans++;
                    }
            }
            
        printf("%d",ans>>1);
    }
    View Code

    dis[i][j] 表示 到第i个点,用了j次传送的最快时间

    堆优化的dijkstra

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 501
    #define M 2001
    
    int n,m,g,k;
    
    int front[N],to[M<<1],nxt[M<<1],val[M<<1],tot;
    bool fly[M<<1];
    
    int DIS[N][2001];
    
    struct node
    {
        int tim,dis,num;
        bool operator < (node p) const
        {
            return dis>p.dis;
        }
    }cur,nt;
    
    priority_queue<node>q;
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v,int w,bool fl)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w; fly[tot]=fl;
    }
    
    void init()
    {
        read(n); read(m); read(g); read(k);
        int u,v,w;
        k=min(g,k);
        while(m--)
        {
            read(u); read(v); read(w);
            add(u,v,w,0);
        }
        while(g--)
        {
            read(u); read(v); read(w);
            add(u,v,w,1);
        }
    }
    
    void dijkstra()
    {
        memset(DIS,63,sizeof(DIS));
        cur.dis=0; cur.num=1; cur.tim=0;
        DIS[1][0]=0;
        q.push(cur);
        while(!q.empty())
        {
            cur=q.top(); q.pop();
            if(cur.num==n)
            {
                printf("%d",cur.dis);
                return;
            }
            if(DIS[cur.num][cur.tim]!=cur.dis) continue;
            for(int i=front[cur.num];i;i=nxt[i])
            {
                if(DIS[to[i]][cur.tim+fly[i]]<cur.dis+val[i]) continue;
                if(cur.tim+fly[i]>k) continue;
                DIS[to[i]][cur.tim+fly[i]]=cur.dis+val[i];
                nt.dis=cur.dis+val[i];
                nt.tim=cur.tim+fly[i];
                nt.num=to[i];
                q.push(nt);
            }
        }
        printf("-1");
    }
    
    int main()
    {
        freopen("move.in","r",stdin);
        freopen("move.out","w",stdout);
        init();
        dijkstra();
        return 0;
    }
    View Code

    相当于把树分成许多块,每一个块的大小>=k,求分块方案数

    树上背包

    dp[i][j] 以i为根子树内,块的大小为j的方案数

    g[j] 当前大小为j的块的方案数

    cnt[i] 以i为根节点的块,大小>=k的方案数

    假设当前正在合并u的子节点 v

    v所在块 如果本身就>=k,那么v可以不并入u,g[j]=cnt[v]*dp[u][j]

    枚举已经与u合并的块的大小j

    枚举v所在块的大小h

    g[j+h]+=dp[x][j]*dp[v][h]

    合并u和v,把g赋给dp

    最后处理完u的时候更新cnt

    注意师最后合并,这样可以使时间复杂度降到 n^2

    相当于每对点只在LCA处有贡献

    #include<cstdio>
    #include<iostream>
    
    using namespace std;
    
    #define N 5001
    #define mod 786433
    
    int front[N],to[N<<1],nxt[N<<1],tot;
    
    int siz[N],dp[N][N],g[N],cnt[N];
    
    int k;
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
    }
    
    void init()
    {
        int n;
        read(n); read(k);
        int u,v;
        for(int i=1;i<n;i++)
        {
            read(u); read(v);
            add(u,v);
        }
    }
    
    void dfs(int x,int y)
    {
        siz[x]=1;
        dp[x][1]=1;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=y)
            {
                dfs(to[i],x);
                for(int j=1;j<=siz[x]+siz[to[i]];j++) g[j]=0;
                for(int j=1;j<=siz[x];j++) g[j]=1ll*cnt[to[i]]*dp[x][j]%mod;
                for(int j=1;j<=siz[x];j++)
                    for(int h=1;h<=siz[to[i]];h++)
                        g[j+h]=(g[j+h]+1ll*dp[x][j]*dp[to[i]][h]%mod)%mod;
                for(int j=1;j<=siz[x]+siz[to[i]];j++) dp[x][j]=g[j];
                siz[x]+=siz[to[i]];
            }
        for(int i=k;i<=siz[x];i++) cnt[x]+=dp[x][i],cnt[x]%=mod;
    }
    
    int main()
    {
        freopen("cut.in","r",stdin);
        freopen("cut.out","w",stdout);
        init();
        dfs(1,0);
        int ans=0;
        for(int i=k;i<=siz[1];i++) ans+=dp[1][i],ans%=mod;
        printf("%d",ans);
    }
    View Code

    2^n  20分暴力

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 5001
    
    int n,k;
    
    int front[N],to[N<<1],nxt[N<<1],from[N<<1],tot;
    
    int ans,cnt;
    
    bool use[N];
    
    int siz[N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; from[tot]=v;
    }
    
    void init()
    {
        read(n); read(k);
        int u,v;
        for(int i=1;i<n;i++)
        {
            read(u); read(v);
            add(u,v);
        }
    }
    
    void dfs2(int x,int y)
    {
        cnt++;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=y && use[i]) dfs2(to[i],x);
    }
    
    void judge()
    {
        for(int i=1;i<=n;i++)
        {
            cnt=0;
            dfs2(i,0);
            if(cnt<k) return;
        }
        ans++;
    }
    
    void dfs(int x)
    {
        if(x==(n-1)*2+1) 
        {
            judge();
            return;
        }
        dfs(x+2);
        use[x]=use[x+1]=true; dfs(x+2); use[x]=use[x+1]=false;
    }
    
    int main()
    {
        freopen("cut.in","r",stdin);
        freopen("cut.out","w",stdout);
        init();
        dfs(1);
        printf("%d",ans); 
    }
    View Code
  • 相关阅读:
    MinGW GCC 7.1.0 2017年6月份出炉啦
    java面试题-框架篇九
    spring-AOP原理
    spring的bean管理(注解)
    23种设计模式(1)-单例模式
    SSH框架面试题集锦
    JQuery基础
    实现用户注册
    spring与hibernate的整合
    spring-IOC理解1
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7717287.html
Copyright © 2011-2022 走看看