zoukankan      html  css  js  c++  java
  • 题解 洛谷 P3734 【[HAOI2017]方案数】

    可以先考虑没有障碍物的情况,设计状态(f_{i,j,k}),表示到达坐标 ((x,y,z))二进制下,(x)(i)位,(y)(j)位,(z)(k)位的方案数。

    得转移方程为:

    [ f_{i,j,k}=sum_{x=1}^i f_{i-x,j,k}inom{i}{x}+sum_{x=1}^j f_{i,j-x,k}inom{j}{x}+sum_{x=1}^k f_{i,j,k-x}inom{k}{x} ]

    对所有障碍物的位置和最终的终点一起考虑,先将这些点按(x)为第一关键字,(y)为第二关键字,(z)为第三关键字排序,保证后面转移的合法。

    (g_i)为到达第(i)个点且不经过排序后顺序该点之前的点的方案数。对于(g_i),计算时通过容斥,为从((0,0,0))到该点不考虑障碍物的方案数,减去其他可以到达该点的点走过来的方案数,判断是否可以到达需看是否三维都是该点子集。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 20010
    #define maxm 70
    #define all 65
    #define mod 998244353
    #define lowbit(x) (x&(-x))
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    ll n,m,r,tot;
    ll f[maxm][maxm][maxm],g[maxn],C[maxm][maxm];
    int get(ll x)
    {
        int cnt=0;
        while(x) cnt++,x-=lowbit(x);
        return cnt;
    }
    struct node
    {
        ll x,y,z;
        int a,b,c;
        void init()
        {
            a=get(x),b=get(y),c=get(z);
        }
    }p[maxn];
    bool cmp(const node &a,const node &b)
    {
        if(a.x==b.x&&a.y==b.y) return a.z<b.z;
        if(a.x==b.x) return a.y<b.y;
        return a.x<b.x;
    }
    int main()
    {
        read(n),read(m),read(r),read(tot);
        for(int i=1;i<=tot;++i)
            read(p[i].x),read(p[i].y),read(p[i].z),p[i].init();
        p[++tot]=(node){n,m,r},p[tot].init(),sort(p+1,p+tot+1,cmp);
        for(int i=0;i<=all;++i) C[i][0]=1;
        for(int i=1;i<=all;++i)
            for(int j=1;j<=i;++j)
                C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
        f[0][0][0]=1;
        for(int i=0;i<=all;++i)
        {
            for(int j=0;j<=all;++j)
            {
                for(int k=0;k<=all;++k)
                {
                    for(int x=1;x<=i;++x) f[i][j][k]=(f[i][j][k]+f[i-x][j][k]*C[i][x]%mod)%mod;
                    for(int x=1;x<=j;++x) f[i][j][k]=(f[i][j][k]+f[i][j-x][k]*C[j][x]%mod)%mod;
                    for(int x=1;x<=k;++x) f[i][j][k]=(f[i][j][k]+f[i][j][k-x]*C[k][x]%mod)%mod;
                }
            }
        }
        for(int i=1;i<=tot;++i)
        {
            g[i]=f[p[i].a][p[i].b][p[i].c];
            for(int j=1;j<i;++j)
            {
                if((p[j].x&p[i].x)!=p[j].x||(p[j].y&p[i].y)!=p[j].y||(p[j].z&p[i].z)!=p[j].z) continue;
                g[i]=(g[i]-g[j]*f[p[i].a-p[j].a][p[i].b-p[j].b][p[i].c-p[j].c]%mod+mod)%mod;
            }
        }
        printf("%lld",g[tot]);
        return 0;
    }
    
  • 相关阅读:
    第二阶段冲刺第二天
    第二阶段冲刺第一天
    学习进度表_十四周
    购买图书
    学习进度表_十三周
    寻找水王续
    学习进度表_十二周
    《梦断代码》读后笔记_4
    找水王
    学习进度表_十一周
  • 原文地址:https://www.cnblogs.com/lhm-/p/13063964.html
Copyright © 2011-2022 走看看