zoukankan      html  css  js  c++  java
  • 2017.10.2 QBXT 模拟赛

    题目链接

    T1

    我们所要求得是(a*b)|x 
    也就是 使(a*b)的倍数小于x的个数之和 1<=x<=n 
    我们可以 找一个c使得 (a*b*c)<=x  
    由于我们所求的是一个三元有序对 即 (1,2,3) 与 (1,3,2) 是两种不同的方案数
    所以 我们可以强制规定 a<b<c 
    最坏的情况是(a*a*a)==x  所以我们就可以确定a的枚举范围 就是n开三次根号
    同理 b最大枚举到 sqrt(n/a) 
    n/(a*b) 即为 c 由于c>b>a 所以 我们枚举的c是大于b的 
    c的实际个数为 n(a*b)-b 
    每一个三元有序对一共有六种变换方式 最后*6加进ans 
    还有一种情况是 a,b,c 中有两个数相等 例如 a==b>c 
    我们只需要枚举 c==n/(a*a) 的个数 
    每一个三元有序对 可以有三种变换  枚举的c的个数最后*3 加进ans 
    最后一种情况就是 a==b==c 对ans的贡献为 1 简单判断一下就好了 
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    
    using namespace std;
    
    long long n;
    
    #ifdef unix
    #define LL "%lld"
    #else
    #define LL "%I64d"
    #endif
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    
        scanf(LL,&n);
        long long ans=0,tmp=0;
        for (long long a=1,v;a*a<=(v=n/a);a++,ans++)
            for (long long b=a+1;b*b<=v;b++)
                tmp+=n/(a*b)-b;
        ans+=tmp*6;
        tmp=0;
        for (long long a=1,v;(v=a*a)<=n;a++)
        {
            tmp+=n/v;
            if (a*a<=n/a) tmp--;
        }
        ans+=tmp*3;
        printf(LL "
    ",ans);
    
        return 0;
    }
    View Code

    T2

     倍增LCA 巧妙地搞一搞 
     对于两个人 想要最大的权值 一定要先把对方给封锁 
     就是 让对方走过的点越少越好 
     所以 两个人 一定是先对着走 
     树上任意两个点之间的路径是唯一的 所以两个人碰面的点 也是一定的 
     即为 两个人之间点数的中位数 
     这个点用LCA 求出 
     求出之后 这个点还可能连着多条边 
     对于先手会先选一颗权值最大的子树 先走一条边
     后手会选次大的子树 走一条边
     两者退回继续选取要走的子树 
     直到走不动了 
     最后ans再加上已经占领的子树的权值 即为最大权值 
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn=100010;
    
    int n,m,en,z[maxn*3],f[maxn][20],q[maxn],depth[maxn],sum[maxn*3][2],fd[maxn],start[maxn],end[maxn],value[maxn];
    
    struct edge
    {
        int e,d;
        edge *next;
    }*v[maxn],ed[maxn<<1];
    
    void add_edge(int s,int e,int d)
    {
        en++;
        ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->d=d;
    }
    
    int get(int p,int d)
    {
        if (d==-1) return p;
        int x=0;
        while (d)
        {
            if (d&1) p=f[p][x];
            d>>=1;
            x++;
        }
        return p;
    }
    
    int get_lca(int p1,int p2)
    {
        if (depth[p1]<depth[p2]) swap(p1,p2);
        p1=get(p1,depth[p1]-depth[p2]);
        int x=0;
        while (p1!=p2)
        {
            if (!x || f[p1][x]!=f[p2][x])
            {
                p1=f[p1][x];
                p2=f[p2][x];
                x++;
            }
            else x--;
        }
        return p1;
    }
    
    int calc(int p1,int p2)
    {
        if (p1==f[p2][0]) return value[1]-value[p2];
        else return value[p1]+fd[p1];
    }
    
    int calcp(int p,int v)
    {
        int l=start[p]-1,r=end[p];
        while (l+1!=r)
        {
            int m=(l+r)>>1;
            if (v>z[m]) l=m;
            else r=m;
        }
        return r;
    }
    
    int main()
    {
        freopen("b.in","r",stdin);
        freopen("b.out","w",stdout);
    
        scanf("%d%d",&n,&m);
        int tot=0;
        for (int a=1;a<n;a++)
        {
            int s,e,d;
            scanf("%d%d%d",&s,&e,&d);
            tot+=d;
            add_edge(s,e,d);
            add_edge(e,s,d);
        }
        depth[1]=1;
        int front=1,tail=1;
        q[1]=1;
        for (;front<=tail;)
        {
            int now=q[front++];
            for (edge *e=v[now];e;e=e->next)
                if (!depth[e->e])
                {
                    depth[e->e]=depth[now]+1;
                    fd[e->e]=e->d;
                    f[e->e][0]=now;
                    int p=now,x=0;
                    while (f[p][x])
                    {
                        f[e->e][x+1]=f[p][x];
                        p=f[p][x];
                        x++;
                    }
                    q[++tail]=e->e;
                }
        }
        int cnt=0;
        for (int a=n;a>=1;a--)
        {
            int now=q[a];
            start[now]=cnt+1;
            for (edge *e=v[now];e;e=e->next)
                if (depth[e->e]==depth[now]+1)
                {
                    z[++cnt]=value[e->e]+e->d;
                    value[now]+=value[e->e]+e->d;
                }
            z[++cnt]=tot-value[now];
            end[now]=cnt;
            sort(z+start[now],z+end[now]+1);
            sum[end[now]][0]=z[end[now]];
            sum[end[now]][1]=0;
            for (int a=end[now]-1;a>=start[now];a--)
            {
                sum[a][0]=sum[a+1][0];
                sum[a][1]=sum[a+1][1];
                if ((a&1)==(end[now]&1)) sum[a][0]+=z[a];
                else sum[a][1]+=z[a];
            }
            cnt++;
        }
        for (int a=1;a<=m;a++)
        {
            int p1,p2;
            scanf("%d%d",&p1,&p2);
            int lca=get_lca(p1,p2);
            int dist=depth[p1]+depth[p2]-2*depth[lca];
            int delta=dist/2+(dist&1);
            int px,px1,px2;
            if (depth[p1]-depth[lca]<delta) px=get(p2,dist-delta);
            else px=get(p1,delta);
            if (depth[p1]-depth[lca]<delta-1) px1=get(p2,dist-delta+1);
            else px1=get(p1,delta-1);
            if (depth[p2]-depth[lca]<dist-delta-1) px2=get(p1,delta+1);
            else px2=get(p2,dist-delta-1);
            int ans=0;
            if (p1==px)
            {
                if (p2==px) ans=sum[start[px]][0];
                else
                {
                    int v2=calc(px2,px);
                    int p=calcp(px,v2);
                    ans=sum[p+1][0]+sum[start[px]][1]-sum[p][1];
                }
            }
            else
            {
                if (p2==px)
                {
                    int v1=calc(px1,px);
                    int p=calcp(px,v1);
                    ans=v1+sum[p+1][1]+sum[start[px]][0]-sum[p][0];
                }
                else
                {
                    int v1=calc(px1,px);
                    int pp1=calcp(px,v1);
                    int v2=calc(px2,px);
                    int pp2=calcp(px,v2);
                    if (pp2==pp1) pp2++;
                    if (pp1>pp2) swap(pp1,pp2);
                    ans=v1+sum[pp2+1][dist&1]+sum[pp1+1][1-(dist&1)]-sum[pp2][1-(dist&1)]+sum[start[px]][dist&1]-sum[pp1][dist&1];
                }
            }
            printf("%d
    ",ans);
        }
    
        return 0;
    }
    View Code

    T3

    怀疑人生的搜索加9维DP
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    #define now pre[a][b][c][d][e][s1][s2][s3][s4]
    #define dis(a,b,c,d) (abs(a-c)+abs(b-d))
    
    const int INF=0x3f3f3f3f;
    
    int A,B,C,D,E,num[10][10],value[10][10][10],delta[10][10][40],dp[31][6][6][6][6][2][2][2][2];
    
    char s[500];
    
    bool map[6][6][6][6];
    
    int main()
    {
        freopen("c.in","r",stdin);
        freopen("c.out","w",stdout);
    
        scanf("%d%d%d%d%d",&A,&B,&C,&D,&E);
        for (int a=0;a<6;a++)
        {
            scanf("%s",s);
            int p=0;
            for (int b=0;b<6;b++)
            {
                int px=p;
                while (s[px]!=']')
                    px++;
                p++;
                num[a][b]=s[p]-'0';
                p++;
                p++;
                for (int c=1;c<=num[a][b];c++)
                {
                    int v=0;
                    while (s[p]>='0' && s[p]<='9')
                    {
                        v=v*10+s[p]-'0';
                        p++;
                    }
                    value[a][b][c]=v;
                    p++;
                }
                p=px+1;
            }
        }
        int base=0;
        for (int a=0;a<6;a++)
            for (int b=0;b<6;b++)
                if (a>=2 && a<=3 && b>=2 && b<=3) ;
                else
                {
                    sort(value[a][b]+1,value[a][b]+num[a][b]+1);
                    for (int c=2;c<=num[a][b];c++)
                        if (value[a][b][c]-value[a][b][c-1]==1) base+=A;
                    for (int c=2;c<=3;c++)
                        for (int d=2;d<=3;d++)
                        {
                            if (dis(a,b,c,d)==1)
                            {
                                for (int e=1;e<=num[a][b];e++)
                                {
                                    delta[c][d][value[a][b][e]]+=B;
                                    delta[c][d][value[a][b][e]-1]+=C;
                                    delta[c][d][value[a][b][e]+1]+=C;
                                }
                            }
                            if (dis(a,b,c,d)==2)
                            {
                                for (int e=1;e<=num[a][b];e++)
                                {
                                    delta[c][d][value[a][b][e]]+=D;
                                    delta[c][d][value[a][b][e]-1]+=E;
                                    delta[c][d][value[a][b][e]+1]+=E;
                                }
                            }
                        }
                    for (int c=0;c<6;c++)
                        for (int d=0;d<6;d++)
                            if (dis(a,b,c,d)<=2 && (c!=a || d!=b) && !map[a][b][c][d])
                            {
                                map[a][b][c][d]=map[c][d][a][b]=true;
                                if (c>=2 && c<=3 && d>=2 && d<=3) ;
                                else
                                {
                                    int dist=dis(a,b,c,d);
                                    for (int e=1;e<=num[a][b];e++)
                                        for (int f=1;f<=num[c][d];f++)
                                        {
                                            if (abs(value[a][b][e]-value[c][d][f])==0)
                                            {
                                                if (dist==1) base+=B;
                                                else base+=D;
                                            }
                                            if (abs(value[a][b][e]-value[c][d][f])==1)
                                            {
                                                if (dist==1) base+=C;
                                                else base+=E;
                                            }
                                        }
                                }
                            }
                }
        memset(dp,0x3f,sizeof(dp));
        dp[0][0][0][0][0][0][0][0][0]=base;
        for (int a=0;a<30;a++)
            for (int b=0;b<=num[2][2];b++)
                for (int c=0;c<=num[2][3];c++)
                    for (int d=0;d<=num[3][2];d++)
                        for (int e=0;e<=num[3][3];e++)
                            for (int s1=0;s1<=1;s1++)
                                for (int s2=0;s2<=1;s2++)
                                    for (int s3=0;s3<=1;s3++)
                                        for (int s4=0;s4<=1;s4++)
                                            if (dp[a][b][c][d][e][s1][s2][s3][s4]!=INF)
                                            {
                                                int v=dp[a][b][c][d][e][s1][s2][s3][s4];
                                                for (int sx1=0;sx1<=(b!=num[2][2]);sx1++)
                                                    for (int sx2=0;sx2<=(c!=num[2][3]);sx2++)
                                                        for (int sx3=0;sx3<=(d!=num[3][2]);sx3++)
                                                            for (int sx4=0;sx4<=(e!=num[3][3]);sx4++)
                                                            {
                                                                int wmt=0;
                                                                if (sx1) 
                                                                {
                                                                    wmt+=delta[2][2][a+1];
                                                                    if (s1) wmt+=A;
                                                                    if (s2) wmt+=C;
                                                                    if (s3) wmt+=C;
                                                                    if (s4) wmt+=E;
                                                                }
                                                                if (sx2) 
                                                                {
                                                                    wmt+=delta[2][3][a+1];
                                                                    if (s1) wmt+=C;
                                                                    if (s2) wmt+=A;
                                                                    if (s3) wmt+=E;
                                                                    if (s4) wmt+=C;
                                                                }
                                                                if (sx3) 
                                                                {
                                                                    wmt+=delta[3][2][a+1];
                                                                    if (s1) wmt+=C;
                                                                    if (s2) wmt+=E;
                                                                    if (s3) wmt+=A;
                                                                    if (s4) wmt+=C;
                                                                }
                                                                if (sx4) 
                                                                {
                                                                    wmt+=delta[3][3][a+1];
                                                                    if (s1) wmt+=E;
                                                                    if (s2) wmt+=C;
                                                                    if (s3) wmt+=C;
                                                                    if (s4) wmt+=A;
                                                                }
                                                                if (sx1 && sx2) wmt+=B;
                                                                if (sx1 && sx3) wmt+=B;
                                                                if (sx1 && sx4) wmt+=D;
                                                                if (sx2 && sx3) wmt+=D;
                                                                if (sx2 && sx4) wmt+=B;
                                                                if (sx3 && sx4) wmt+=B;
                                                                int &t=dp[a+1][b+sx1][c+sx2][d+sx3][e+sx4][sx1][sx2][sx3][sx4];
                                                                if (t>v+wmt) t=v+wmt;
                                                            }
                                            }
        int ans=INF;
        for (int a=0;a<=1;a++)
            for (int b=0;b<=1;b++)
                for (int c=0;c<=1;c++)
                    for (int d=0;d<=1;d++)
                        ans=min(ans,dp[30][num[2][2]][num[2][3]][num[3][2]][num[3][3]][a][b][c][d]);
        printf("%d
    ",ans);
    
        return 0;
    }
    View Code
  • 相关阅读:
    Binary Tree Maximum Path Sum
    ZigZag Conversion
    Longest Common Prefix
    Reverse Linked List II
    Populating Next Right Pointers in Each Node
    Populating Next Right Pointers in Each Node II
    Rotate List
    Path Sum II
    [Leetcode]-- Gray Code
    Subsets II
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7646737.html
Copyright © 2011-2022 走看看