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\n",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\n",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\n",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\n",L,V);
            }
    }

    return 0;
}
View Code

 

posted @ 2015-09-19 10:35  来自大山深处的菜鸟  阅读(300)  评论(0编辑  收藏  举报