• BestCoder Round #55 ($)


    C

     构造一个矩阵,然后采用矩阵快速幂

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <cstdio>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const LL mod = 1000000007;
    const int maxn=1<<7;
    struct Matix
    {
        LL m[maxn][maxn];
        int n;
        Matix mul(Matix &rhs)
        {
             Matix ans;
             for(int i=0; i<n; i++)
                 for(int j=0; j<n; j++)
                 {
                    ans.m[i][j]=0;
                    for(int k=0; k<n; k++)
                     ans.m[i][j]=(ans.m[i][j]+m[i][k]*rhs.m[k][j])%mod;
                 }
                ans.n=n;
            return ans;
        }
    };
    Matix T;
    LL powmod(int n,int m)
    {
         Matix ans,A=T;
         ans.n=1<<m;
         memset(ans.m,0,sizeof(ans.m));
         for(int i=0; i<ans.n; i++)
            ans.m[i][i]=1;
         while(n){
             if(n&1)ans=ans.mul(A);
             n>>=1;
             A=A.mul(A);
         }
         LL an=0;
         for(int i=0; i<ans.n; i++){
             an=(ans.m[i][0]+an)%mod;
         }
         return an;
    }
    int jud(int A, int B, int m)
    {
         for(int i=0; i<m; i++)
            {
                if(A&(1<<i)){
                    if(B&(1<<i))continue;
                    if(i&&(B&(1<<(i-1)))>0 && (A&(1<<(i-1)))==0 )return 0;
                    if(i!=m-1&&(B&(1<<(i+1)))>0&&(A&(1<<(i+1)))==0)return 0;
                }
            }
            return 1;
    }
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)==2)
        {
    
            for(int i=0; i<(1<<m); i++)
             {
                 for(int j=0; j<(1<<m); j++)
                 {
    
                      T.m[i][j]=jud(i,j,m);
                 }
    
             }
             T.n=(1<<m);
             printf("%I64d
    ",powmod(n,m));
        }
        return 0;
    }
    View Code

    D

    计算[a,b]之间的所有数的各个位置异或然后整个区间求和, 我们用d[i][j]表示在第i位时异或为j的个数,然后我们枚举每一位,求和就好了,因为10以内的数异或小于16

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <cstdio>
    using namespace std;
    typedef long long LL;
    const LL mod = 1000000007;
    const int maxn=100000+10;
    LL dp[maxn][10],d[maxn][16];
    void solve()
    {
        d[0][0]=1;
        for(int i=1; i<100001; i++)
        {
             for(int j=0; j<10; j++)
              for(int r=0; r<16; r++){
                 d[i][r]=d[i][r]+d[i-1][r^j];
                 if(d[i][r]>=mod)d[i][r]-=mod;
              }
        }
    }
    char str[maxn];
    LL look(int n,int op)
    {
         int nt=0;
         LL ans=0;
         for(int i=n; i>0; i--){
                int lit=str[n-i]-'0';
             for(int j=0; j<lit; j++){
                 int dr=nt^j;
                 for(int k=0; k<16; k++){
                    ans=(ans+d[i-1][k^dr]*k )%mod;
                 }
             }
                nt^=lit;
         }
         if(op)
         ans=(ans+nt)%mod;
         return ans;
    }
    int main()
    {
        int cas;
        solve();
        scanf("%d",&cas);
        for(int  cc=1 ;cc<=cas; cc++)
        {
             LL ans=0;
             scanf("%s",str);
             int len=strlen(str);
             ans=ans-look(len,0);
             scanf("%s",str);
             len=strlen(str);
             LL a1=look(len,1);
             ans=( (ans+a1)%mod+mod )%mod;
             printf("Case #%d: %I64d
    ",cc,ans);
        }
        return 0;
    }
    View Code

    E

    给了一棵树50000个节点求从100000 次查询 每次给了两个点求两个节的路径最小并且最大值最大,每个叶子节点能回到1这个节点,我们考虑几种情况,

     树上直接链的 , 还有就是通过叶子节点回到1 1再转化,  这里有个坑点就是 一个点可以到叶子节点后 还可能通过他的父亲到达叶子节点,不一定是通过他的孩子,坑了好久

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string.h>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const int numofedg=100000+10;
    const int maxn=500005;
    int H[maxn],nx[numofedg],to[numofedg],numofE,val[maxn];
    int son[maxn],num[maxn],fa[maxn],top[maxn],p[maxn],fp[maxn],pos,depth[maxn],ans[maxn];
    int minDown[maxn],maxDown[maxn],minUp[maxn],maxUp[maxn];
    void init(int n)
    {
        val[0]=0;maxUp[0]=minUp[0]=0;
        numofE=0;pos=0;
        memset(H,0,sizeof(H));
    }
    void addedg(int a, int b){
         numofE++;
         to[numofE]=b;
         nx[numofE]=H[a];
         H[a]=numofE;
    }
    void panduan(int &L, int &V, int L2,int V2){
         if(L>=L2){
             if(L == L2 ){
                V=V>V2?V:V2;
                }else {
                    L=L2;
                    V=V2;
                }
         }
    }
    void dfs(int cur, int per, int dep)
    {
        depth[cur]=dep;
        son[cur]=-1;
        fa[cur]=per;
        num[cur]=1;
        maxUp[cur]=max( val[ cur ] , maxUp[ per ] );
        minUp[cur]=minUp[per] + val[cur];
        maxDown[ cur ]=-1;
        minDown[ cur ]=1000000000;
        for(int i=H[cur]; i>0 ; i=nx[i])
            {
                int tto=to[i];
                if(tto==per)continue;
                dfs(tto,cur,dep+1);
                num[cur]+=num[tto];
                panduan(minDown[cur],maxDown[cur],minDown[tto],maxDown[tto]);
                if( son[cur]==-1 || num[ son[cur] ] < num[ tto ] )son[cur]=tto;
            }
            if(son[cur]!=-1){
                maxDown[cur]=max(maxDown[cur],val[cur]);
                minDown[cur]+=val[cur];
    
            }else{
                maxDown[cur]=val[cur];
                minDown[cur]=val[cur];
            }
    }
    void finde(int cur ,int per, int xx)
    {
        top[cur]=xx;
        pos++;
        p[cur]=pos;
        fp[pos]=cur;
        if(son[cur]!=-1)
            finde(son[cur],cur,xx);
        for(int i=H[cur]; i>0; i=nx[i])
            {
                if(to[i]==son[cur]||to[i]==per)continue;
                finde(to[i],cur,to[i]);
            }
    }
    struct Itree
    {
       int sum[maxn*5],maxval[ maxn*5],CL,CR;
       int S,Ma;
       void build(int L, int R, int o)
       {
          if(L==R)
            {
                maxval[ o ] = sum[ o ] = val[ fp[L] ];
                return ;
            }
           int mid=(L+R)>>1;
           build(L,mid,o*2);
           build(mid+1,R,o*2+1);
           maxval[o]=max(maxval[o*2],maxval[o*2+1]);
           sum[o]=sum[o*2]+sum[o*2+1];
       }
       void query(int L, int R, int o)
       {
            if(CL<=L&&R<=CR){
                S=S+sum[o];
                Ma=max(maxval[o],Ma); return ;
            }
            int mid=(L+R)>>1;
            if(CL<=mid)
                query(L,mid,o*2);
            if(CR>mid)
                query(mid+1,R,o*2+1);
       }
    }T;
    struct QE{
     int L,R;
     QE(int cL=0,int cR=0){
        L=cL; R=cR;
     }
    };
    vector<QE>Qnu;
    void solve(int x, int y)
    {
        int f1=top[x],f2=top[y];
        while(f1!=f2){
            if(depth[f1]<depth[f2]){
                int temp=x;x=y; y=temp;
                temp=f1;f1=f2;f2=temp;
            }
            Qnu.push_back( QE(p[f1],p[x]) );
            x=fa[f1];
            f1=top[x];
        }
        if(depth[x]>depth[y]){
            int temp=x; x=y; y=temp;
        }
        Qnu.push_back(QE(p[x],p[y]));
    }
    void jud2(int u, int v, int &L, int &V,int n)
    {
         Qnu.clear();
         solve(u,v);
         T.S=0;
         T.Ma=-1;
         for(int i=0; i<Qnu.size(); i++)
            {
                QE t=Qnu[i];
                T.CL=min(t.L,t.R);
                T.CR=max(t.L,t.R);
                T.query(1,n,1);
            }
         L=T.S;V=T.Ma;
    }
    void dfs2(int cur, int per)
    {
         if(cur!=1){
            panduan(minDown[cur],maxDown[cur],minDown[per]+val[cur],max(maxDown[per],val[cur]));
         }
         for(int i=H[cur]; i>0; i=nx[i])
            dfs2(to[i],cur);
    }
    void jud1(int uu, int vv, int &L, int &V)
    {
        L=minDown[uu]+minUp[vv];
        V=max(maxDown[uu],maxUp[vv]);
        int L2,V2;
        L2=minDown[uu]+minDown[vv]+val[1];
        V2=max(maxDown[uu],max(maxDown[vv],val[1]));
        panduan(L,V,L2,V2);
    
        L2=minUp[uu]+minDown[vv];
        V2=max(maxUp[uu],maxDown[vv]);
    
        panduan(L,V,L2,V2);
    }
    int main()
    {
        int cas,n,m;
        scanf("%d",&cas);
        for(int cc=1; cc<=cas ;cc++)
        {
            scanf("%d%d",&n,&m);
            init(n);
            for(int i=2; i<=n; i++)
                {
                  int d;
                  scanf("%d",&d);
                  addedg(d,i);
                }
            for(int i=1; i<=n; i++)
                {
                    scanf("%d",&val[i]);
                }
            dfs(1,0,0);
            finde(1,0,1);
            T.build(1,n,1);
            dfs2(1,0);
            for(int i=0; i<m; i++)
                {
                    int u,v;
                    scanf("%d%d",&u,&v);
                    if(u==v){
                        printf("%d %d
    ",val[u],val[v]);
                        continue;
                    }
                    int L,V;
                    jud1(u,v,L,V);
                    int L2,V2;
                    jud2(u,v,L2,V2,n);
                    panduan(L,V,L2,V2);
                    printf("%d %d
    ",L,V);
                }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    java常量和变量的定义规则,变长参数的使用
    测试一下windowsLiveWriter
    对转换公式为LaTeX代码要注意什么
    后台登陆骨架
    为什么要把session存入数据库
    登录功能测试
    数据库快速配置
    一个小bug
    后台测试常需要的htm样式
    在分页的基础上添加删除和(查看,原理和删除一样)
  • 原文地址:https://www.cnblogs.com/Opaser/p/4818440.html
Copyright © 2020-2023  润新知