zoukankan      html  css  js  c++  java
  • [jzoj 5664] [GDOI2018Day1模拟4.6] 凫趋雀跃 解题报告(容斥原理)

    interlinkage:

    https://jzoj.net/senior/#contest/show/2703/3

    description:

    solution:

    考虑容斥原理,枚举不合法的走的步数

    $f_{p,x,y}$表示任意走$p$步走到$x$,$y$的方案数

    $g_{p,x}$表示走不合法的步走$p$步走到$(10*x,10*x)$的方案数

    $g$数组很好得到,发现$f$数组直接暴力转移时间复杂度不对

    但是随意走在横轴和竖轴上是独立的,因此我们可以设$fx_{p,x}$表示在横轴上走$p$步走到位置$x$的方案数,同理得到$fy$数组

    $f_{p,x,y}=fx_{p,x}*fy_{p,y}$

    那么$ans=sum_{i=0}^{R}dbinom{R}{i}sum_{z=0}^{min(Tx,Ty)/10}g_{i,z}*f_{R-i,Tx-10*z,Ty-10*z}$

    注意因为零向量不可走,方便处理我们将它加入不可走的数组中即可,因为$0 mod 10=0$也是成立的

    code:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    
    const int M=1600+15;
    const int mo=1e4+7;
    int Tx,Ty,Mx,My,R,K;
    int fx[M][M],fy[M][M],sum[M],kk[M],g[M][M],C[M][M];
    int main()
    {
        freopen("jump.in","r",stdin);
        freopen("jump.out","w",stdout);
        scanf("%d%d%d%d%d%d",&Tx,&Ty,&Mx,&My,&R,&K);
        for (int j=0;j<=Tx;j++) sum[j]=1;
        for (int i=1;i<=R;i++)
        {
            for (int j=0;j<=Tx;j++) 
            {
                if (j>Mx) fx[i][j]=((sum[j]-sum[j-Mx-1])%mo+mo)%mo;
                else fx[i][j]=sum[j];
            }
            sum[0]=fx[i][0];
            for (int j=1;j<=Tx;j++) sum[j]=(sum[j-1]+fx[i][j])%mo;
        }
        for (int j=0;j<=Ty;j++) sum[j]=1;
        for (int i=1;i<=R;i++)
        {
            for (int j=0;j<=Ty;j++) 
            {
                if (j>My) fy[i][j]=((sum[j]-sum[j-My-1])%mo+mo)%mo;
                else fy[i][j]=sum[j];
            }
            sum[0]=fy[i][0];
            for (int j=1;j<=Ty;j++) sum[j]=(sum[j-1]+fy[i][j])%mo;
        }
        for (int i=1;i<=K;i++) scanf("%d",&kk[i]);kk[++K]=0;
        g[0][0]=1;
        for (int k=1;k<=R;k++)
        {
            for (int i=0;10*i<=min(Tx,Ty);i++)
            {
                for (int j=1;j<=K;j++)
                if (i>=kk[j]/10)
                {
                    (g[k][i]+=g[k-1][i-kk[j]/10])%=mo;
                }
            }
        }
        C[0][0]=1;
        for (int i=1;i<=R;i++)
        {
            C[i][0]=1;
            for (int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mo;
        }
        int ans=0;
        for (int i=0;i<=R;i++)
        {
            if (i&1)
            {
                for (int z=0;z*10<=min(Tx,Ty);z++) (ans-=1ll*C[R][i]*g[i][z]%mo*fx[R-i][Tx-10*z]%mo*fy[R-i][Ty-10*z]%mo)%=mo;
            }
            else 
            {
                for (int z=0;z*10<=min(Tx,Ty);z++) (ans+=1ll*C[R][i]*g[i][z]%mo*fx[R-i][Tx-10*z]%mo*fy[R-i][Ty-10*z]%mo)%=mo;
            }
        }
        ans=(ans%mo+mo)%mo;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    简单明了理解Java移位运算符
    mybatis(1):入坑篇
    货币格式化
    100 doors
    Object调用静态方法
    Rust入门篇 (1)
    BOM-字节序标记
    【Linux】设定一个能输入中文的英文环境!
    正则表达式验证 输入内容为小数位不超过2位的数值
    创建一个springMVC项目总结
  • 原文地址:https://www.cnblogs.com/xxzh/p/10662980.html
Copyright © 2011-2022 走看看