【JZOJ6403】a

百般思念 提交于 2019-12-03 13:06:46

description


analysis

  • 考虑\((0,0,0)\)走到某个点\((i,j,k)\)贡献,相当于插板问题

  • \(i+j\)个空插\(k\)个板可以有空,\(i\)个空插\(j\)个板可以有空,就是\(C^k_{i+j+k}*C^j_{i+j}\)

  • 对于每个障碍,要算出被它包含的障碍走到它的合法方案数少了多少

  • 那么就是拿答案减去走到被包含的障碍的答案乘右上角矩形的贡献


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAX 300000
#define ha 1000000007
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)

using namespace std;

ll fac[300005],inv[300005];
ll f[305][305][305];
bool bz[305][305][305];
ll n,m;

struct node
{
    ll x,y,z,ans;
}a[5005];

inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
    while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline ll cube(ll x){return x*x%ha*x%ha;}
inline ll pow(ll x,ll y)
{
    ll z=1;
    while (y){if (y&1)z=z*x%ha;x=x*x%ha,y>>=1;}
    return z;
}
inline ll C(ll m,ll n){return fac[n]*inv[n-m]%ha*inv[m]%ha;}
inline ll get(ll i,ll j,ll k){return C(k,i+j+k)*C(j,i+j)%ha;}
inline bool cmp(node a,node b){return a.x<b.x || (a.x==b.x && a.y<b.y) || (a.x==b.x && a.y==b.y && a.z<b.z);}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);    
    n=read(),m=read();
    if (!m)
    {
        fac[0]=1;fo(i,1,MAX)fac[i]=fac[i-1]*i%ha;
        printf("%lld\n",fac[3*n]*pow(cube(fac[n]),ha-2)%ha);
        return 0;
    }
    if (n<=300)
    {
        memset(bz,1,sizeof(bz)),f[0][0][0]=1;
        fo(i,1,m)bz[read()][read()][read()]=0;
        fo(i,0,n)fo(j,0,n)fo(k,0,n)
        {
            if (bz[i+1][j][k])(f[i+1][j][k]+=f[i][j][k])%=ha;
            if (bz[i][j+1][k])(f[i][j+1][k]+=f[i][j][k])%=ha;
            if (bz[i][j][k+1])(f[i][j][k+1]+=f[i][j][k])%=ha;
        }
        printf("%lld\n",f[n][n][n]);
        return 0;
    }
    fac[0]=inv[0]=1;fo(i,1,MAX)fac[i]=fac[i-1]*i%ha;
    inv[MAX]=pow(fac[MAX],ha-2);fd(i,MAX-1,1)inv[i]=inv[i+1]*(i+1)%ha;
    fo(i,1,m)a[i].x=read(),a[i].y=read(),a[i].z=read(),a[i].ans=get(a[i].x,a[i].y,a[i].z);
    ++m,a[m].x=n,a[m].y=n,a[m].z=n,a[m].ans=get(n,n,n),sort(a+1,a+m+1,cmp);
    fo(i,1,m)fo(j,1,i-1)if (a[i].x>=a[j].x && a[i].y>=a[j].y && a[i].z>=a[j].z)
    a[i].ans=(a[i].ans-a[j].ans*get(a[i].x-a[j].x,a[i].y-a[j].y,a[i].z-a[j].z)%ha+ha)%ha;
    printf("%lld\n",a[m].ans);
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!