BZOJ 4002~4007 JLOI2015 代码

题解戳这里

4002 有意义的字符串:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define P 7528443412579576937ull
using namespace std;
typedef unsigned long long ull;
ull b,d,n;
ull Times(ull x,ull y)
{
    ull re=0;
    while(y)
    {
        if(y&1)
        {
            re+=x;
            if(re>=P)
                re-=P;
        }
        x+=x;
        if(x>=P)
            x-=P;
        y>>=1;
    }
    return re;
}
namespace Matrix_Multiplication{
    struct Matrix{
        ull a[2][2];
        ull* operator [] (int x)
        {
            return a[x];
        }
        friend Matrix& operator *= (Matrix &x,Matrix y)
        {
            int i,j,k;
            Matrix z;
            memset(&z,0,sizeof z);
            for(i=0;i<2;i++)
                for(j=0;j<2;j++)
                    for(k=0;k<2;k++)
                        (z[i][j]+=Times(x[i][k],y[k][j]))%=P;
            return x=z;
        }
    }a;
    //a[i]=b*a[i-1]+(d-b*b)/4*a[i-2]
    //a[0]=2,a[1]=b
    Matrix Quick_Power(Matrix x,ull y)
    {
        Matrix re;
        re[0][0]=re[1][1]=1;
        re[1][0]=re[0][1]=0;
        while(y)
        {
            if(y&1) re*=x;
            x*=x; y>>=1;
        }
        return re;
    }
}
int main()
{
    using namespace Matrix_Multiplication;
    cin>>b>>d>>n;
    a[0][0]=0;
    a[1][0]=1;
    a[0][1]=d-b*b>>2;
    a[1][1]=b;
    Matrix ans=Quick_Power(a,n);
    cout<<(Times(ans[0][0],2)+Times(ans[1][0],b)-(d!=b*b&&~n&1))%P<<endl;
    return 0;
}

4003 城池攻占:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 300300
using namespace std;
struct Heap{

    #define HEIGHT(p) ((p)?(p)->height:0)

    Heap *ls,*rs;
    long long height,val,belong;
    long long times_mark,add_mark;
    void* operator new(size_t,long long _,long long __)
    {
        static Heap mempool[M],*C=mempool;
        C->ls=C->rs=0x0;
        C->height=1;
        C->val=_;
        C->belong=__;
        C->times_mark=1;
        C->add_mark=0;
        return C++;
    }
    void Times(long long x)
    {
        val*=x;
        times_mark*=x;
        add_mark*=x;    
    }
    void Add(long long x)

    {
        val+=x;
        add_mark+=x;
    }
    void Push_Down()
    {
        if(times_mark!=1)
        {
            if(ls) ls->Times(times_mark);
            if(rs) rs->Times(times_mark);
            times_mark=1;
        }
        if(add_mark!=0)
        {
            if(ls) ls->Add(add_mark);
            if(rs) rs->Add(add_mark);
            add_mark=0;
        }
    }
    void Push_Up()
    {
        height=HEIGHT(rs)+1;
    }
    friend Heap* Merge(Heap *x,Heap *y)
    {
        if(!x) return y;
        if(!y) return x;
        if(x->val>y->val)
            swap(x,y);
        x->Push_Down();
        x->rs=Merge(x->rs,y);
        if( HEIGHT(x->rs)>HEIGHT(x->ls) )
            swap(x->ls,x->rs);
        x->Push_Up();
        return x;
    }
}*heap[M];
struct abcd{
    int to,next;
}table[M];
int head[M],tot;
int n,m;
int fa[M],dpt[M],ans[M];
long long h[M],a[M],v[M];
int st[M],ed[M];
void Add(int x,int y)
{
    table[++tot].to=y;
    table[tot].next=head[x];
    head[x]=tot;
}
void Tree_DP()
{
    static int q[M],r,h;
    int i,j;
    q[++r]=1;
    while(r!=h)
    {
        int x=q[++h];
        dpt[x]=dpt[fa[x]]+1;
        for(i=head[x];i;i=table[i].next)
            q[++r]=table[i].to;
    }
    for(j=n;j;j--)
    {
        int x=q[j];
        for(i=head[x];i;i=table[i].next)
            heap[x]=Merge(heap[x],heap[table[i].to]);
        while( heap[x] && heap[x]->val< ::h[x] )
        {
            ed[heap[x]->belong]=x;
            ans[x]++;
            heap[x]->Push_Down();
            heap[x]=Merge(heap[x]->ls,heap[x]->rs);
        }
        if(heap[x])
        {
            if(a[x]==0)
                heap[x]->Add(v[x]);
            else
                heap[x]->Times(v[x]);
        }
    }

}
int main()
{
    int i;long long x,y;
    cin>>n>>m;
    for(i=1;i<=n;i++)
        scanf("%lld",&h[i]);
    for(i=2;i<=n;i++)
    {
        scanf("%d%lld%lld",&fa[i],&a[i],&v[i]);
        Add(fa[i],i);
    }
    for(i=1;i<=m;i++)
    {
        scanf("%lld%lld",&x,&y);
        Heap *temp=new (x,i)Heap;
        st[i]=y;heap[y]=Merge(temp,heap[y]);
    }
    Tree_DP();
    for(i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    for(i=1;i<=m;i++)
        printf("%d\n",dpt[st[i]]-dpt[ed[i]]);
    return 0;
}

4004 装备购买:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 550
#define MOD 999911659
using namespace std;
int n,m,cnt;
long long ans;
long long Quick_Power(long long x,long long y)
{
    long long re=1;
    while(y)
    {
        if(y&1) (re*=x)%=MOD;
        (x*=x)%=MOD; y>>=1;
    }
    return re;
}
struct Vector{
    long long a[M];
    friend istream& operator >> (istream &_,Vector &v)
    {
        int i;
        for(i=1;i<=m;i++)
            scanf("%I64d",&v.a[i]);
        return _;
    }
    void Elimination(const Vector &v,int pos)
    {
        int i;
        long long temp=(MOD-a[pos]*Quick_Power(v.a[pos],MOD-2)%MOD)%MOD;
        for(i=pos;i<=m;i++)
            (a[i]+=temp*v.a[i])%=MOD;
    }
    bool operator < (const Vector &v) const
    {
        return false;
    }
}*linear_bases[M];
pair<int,Vector> a[M];
bool Insert(Vector &v)
{
    int i;
    for(i=1;i<=m;i++)
        if(v.a[i])
        {
            if(!linear_bases[i])
            {
                linear_bases[i]=&v;
                return true;
            }
            v.Elimination(*linear_bases[i],i);
        }
    return false;
}
int main()
{
    int i;
    cin>>n>>m;
    for(i=1;i<=n;i++)
        cin>>a[i].second;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i].first);
    sort(a+1,a+n+1);
    for(i=1;i<=n;i++)
        if(Insert(a[i].second))
            ++cnt,ans+=a[i].first;
    cout<<cnt<<' '<<ans<<endl;
    return 0;
}

4005 骗我呢:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 3003003
#define MOD 1000000007
using namespace std;
int n,m;
long long fac[M],inv[M],ans;
void Linear_Shaker()
{
    int i;
    for(fac[0]=1,i=1;i<=3000000;i++)
        fac[i]=fac[i-1]*i%MOD;
    for(inv[1]=1,i=2;i<=3000000;i++)
        inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
    for(inv[0]=1,i=1;i<=3000000;i++)
        (inv[i]*=inv[i-1])%=MOD;
}
long long C(int n,int m)
{
    if(n<m) return 0;
    return fac[n] * inv[m] % MOD * inv[n-m] % MOD ;
}
long long Calculate(int x,int y)
{
    if(x<0||y<0)
        return 0;
    return C(x+y,x);
}
void Flip1(int &x,int &y)//沿着直线y=x+1翻转
{
    swap(x,y);
    x--;y++;
}
void Flip2(int &x,int &y)//沿着直线y=x-(m+2)翻转
{
    swap(x,y);
    x+=m+2;y-=m+2;
}
int main()
{


    cin>>n>>m;
    Linear_Shaker();

    ans=Calculate(m+n+1,n);

    int x=m+n+1,y=n;
    while(x>=0&&y>=0)
    {
        Flip1(x,y);
        ans-=Calculate(x,y);
        Flip2(x,y);
        ans+=Calculate(x,y);
        ans%=MOD;
    }

    x=m+n+1,y=n;
    while(x>=0&&y>=0)
    {
        Flip2(x,y);
        ans-=Calculate(x,y);
        Flip1(x,y);
        ans+=Calculate(x,y);
        ans%=MOD;
    }

    cout<<(ans+MOD)%MOD<<endl;
    return 0;
}

4006 管道连接:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1010
using namespace std;
struct Key_Point{
    int color,point;
    bool operator < (const Key_Point &k) const
    {
        return color < k.color ;
    }
}points[20],_points[20];
struct abcd{
    int to,f,next;
}table[3030<<1];
int head[M],tot;
int n,m,p,c,cnt;
int f[1024][M],g[32];
int q[65540];
unsigned short r,h;
void Add(int x,int y,int z)
{
    table[++tot].to=y;
    table[tot].f=z;
    table[tot].next=head[x];
    head[x]=tot;
}
void SPFA(int f[])
{
    static bool v[M];
    int i;
    while(r!=h)
    {
        int x=q[++h];v[x]=false;
        for(i=head[x];i;i=table[i].next)
            if(f[table[i].to]>f[x]+table[i].f)
            {
                f[table[i].to]=f[x]+table[i].f;
                if(!v[table[i].to])
                    v[table[i].to]=true,q[++r]=table[i].to;
            }
    }
}
int Steiner_Tree()
{
    int i,j,k;
    for(i=1;i<1<<cnt;i++)
    {
        for(j=1;j<=n;j++)
        {
            for(k=i&(i-1);k;(--k)&=i)
                f[i][j]=min(f[i][j],f[k][j]+f[i^k][j]);
            if(f[i][j]!=0x3f3f3f3f)
                q[++r]=j;
        }
        SPFA(f[i]);
    }
    int ans=0x3f3f3f3f;
    for(i=1;i<=n;i++)
        ans=min(ans,f[(1<<cnt)-1][i]);
    return ans;
}
int main()
{
    int i,j,x,y,z;
    cin>>n>>m>>p;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        Add(x,y,z);Add(y,x,z);
    }
    for(i=1;i<=p;i++)
        scanf("%d%d",&points[i].color,&points[i].point);
    sort(points+1,points+p+1);
    p=0;
    for(i=1;points[i].color;i++)
        if(points[i].color==points[i-1].color||points[i].color==points[i+1].color)
            _points[++p]=points[i];
    memcpy(points,_points,sizeof points);
    for(i=1;i<=p;i++)
    {
        if(i==1||_points[i].color!=_points[i-1].color)
            ++c;
        points[i].color=c;
    }
    memset(g,0x3f,sizeof g);
    for(i=1;i<1<<c;i++)
    {
        cnt=0;
        for(j=1;j<=p;j++)
            if(i&(1<<points[j].color-1))
                ++cnt;
        memset(f,0x3f,sizeof(f[0][0])*M*(1<<cnt));
        cnt=0;
        for(j=1;j<=p;j++)
            if(i&(1<<points[j].color-1))
                f[1<<cnt++][points[j].point]=0;
        g[i]=Steiner_Tree();
    }
    for(i=1;i<1<<c;i++)
        for(j=i&(i-1);j;(--j)&=i)
            g[i]=min(g[i],g[j]+g[i^j]);
    cout<<g[(1<<c)-1]<<endl;
    return 0;
}

4007 战争调度:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1100
using namespace std;
int n,m;
int a[M][M],b[M][M],f[M][M];
//f[i][j]表示以i为根的子树中选择j个参战的最大收益
bool status[M];
void DFS(int x,int size)
{
    int i,j;
    if(x>=1<<n-1)
    {
        f[x][0]=f[x][1]=0;
        for(i=x>>1;i;i>>=1)
            if(status[i]==0)
                f[x][1]+=a[x][i];
            else
                f[x][0]+=b[x][i];
        return ;
    }
    status[x]=false;
    DFS(x<<1,size>>1);DFS(x<<1|1,size>>1);
    int limit=min(size,m);//x所在的子树中最多有limit个平民参战
    memset(f[x],0,sizeof(f[0][0])*(limit+1));
    for(i=0;i<=limit;i++)
    {
        int upper=min(size>>1,i);//左子树最多有upper个平民参战
        int lower=max(i-(size>>1),0);//左子树最少有lower个平民参战
        for(j=lower;j<=upper;j++)
            f[x][i]=max(f[x][i],f[x<<1][j]+f[x<<1|1][i-j]);
    }
    status[x]=true;
    DFS(x<<1,size>>1);DFS(x<<1|1,size>>1);
    for(i=0;i<=limit;i++)
    {
        int upper=min(size>>1,i);//左子树最多有upper个平民参战
        int lower=max(i-(size>>1),0);//左子树最少有lower个平民参战
        for(j=lower;j<=upper;j++)
            f[x][i]=max(f[x][i],f[x<<1][j]+f[x<<1|1][i-j]);
    }
}
int main()
{
    int i,j;
    cin>>n>>m;
    for(i=1<<n-1;i<1<<n;i++)
        for(j=i>>1;j;j>>=1)
            scanf("%d",&a[i][j]);
    for(i=1<<n-1;i<1<<n;i++)
        for(j=i>>1;j;j>>=1)
            scanf("%d",&b[i][j]);
    DFS(1,1<<n-1);
    int ans=0;
    for(i=0;i<=m;i++)
        ans=max(ans,f[1][i]);
    cout<<ans<<endl;
}

你可能感兴趣的:(bzoj,JLOI2015)