51nod 1838

51nod 1838

http://www.51nod.com/Challenge/Problem.html#!#problemId=1838

题目中有一个很巧妙的反演。由于之前没接触过这类题目。第一次接触,感觉学到了很多东西。

首先。计算,无限限制的情况下,从 ( 0 , 0 ) (0,0) (0,0)走到 ( x , y ) (x,y) (x,y),不走 ( 0 , 0 ) (0,0) (0,0)向量的方案数。

由于 x x x方向和 y y y方向有一定关系,又相互独立。
A ( M , R , t ) A(M,R,t) A(M,R,t)表示:
∑ i R a i = t , a i ∈ [ 0 , M ] \sum_i^Ra_i = t,a_i\in[0,M] iRai=t,ai[0,M]
的答案个数。
则有:
∑ i > = 0 A ( M , R , t ) x t = ( ∑ i = 0 M x i ) R \sum_{i>=0}A(M,R,t)x^t=\Big(\sum_{i=0}^Mx^i\Big)^R i>=0A(M,R,t)xt=(i=0Mxi)R
( ∑ i = 0 M x i ) R = ( 1 − x M + 1 1 − x ) R = ( 1 − x ) − R ∑ a = 0 R ( R a ) ( − 1 ) a x ( M + 1 ) a \Big(\sum_{i=0}^Mx^i\Big)^R =\Big(\frac{1-x^{M+1}}{1-x}\Big)^R=(1-x)^{-R}\sum_{a=0}^R\binom{R}{a}(-1)^ax^{(M+1)a} (i=0Mxi)R=(1x1xM+1)R=(1x)Ra=0R(aR)(1)ax(M+1)a
= ∑ a = 0 R ( R a ) ( − 1 ) a x ( M + 1 ) a ∑ b > = 0 ( R + b − 1 b ) x b =\sum_{a=0}^R\binom{R}{a}(-1)^ax^{(M+1)a}\sum_{b>=0}\binom{R+b-1}{b}x^b =a=0R(aR)(1)ax(M+1)ab>=0(bR+b1)xb
则有: A ( M , R , x ) = ∑ a = 0 R ( R a ) ( − 1 ) a ( R + ( x − ( M + 1 ) a ) − 1 x − ( M + 1 ) a ) A(M,R,x) =\sum_{a=0}^R\binom{R}{a}(-1)^a\binom{R+(x-(M+1)a)-1}{x-(M+1)a} A(M,R,x)=a=0R(aR)(1)a(x(M+1)aR+(x(M+1)a)1)

D d ( R , x , y ) D_d(R,x,y) Dd(R,x,y) ( 0 , 0 ) (0,0) (0,0) ( x , y ) (x,y) (x,y) R R R步, d d d ( 0 , 0 ) (0,0) (0,0)向量的方案数.
那么有:
∑ t = 0 R ∑ d = 0 t ( t d ) D t ( R , x , y ) = ∑ d = 0 R ( R d ) A ( M x , R − d , x ) A ( M y , R − d , y ) \sum_{t=0}^R\sum_{d=0}^t\binom{t}{d}D_t(R,x,y)=\sum_{d=0}^R\binom{R}{d}A(M_x,R-d,x)A(M_y,R-d,y) t=0Rd=0t(dt)Dt(R,x,y)=d=0R(dR)A(Mx,Rd,x)A(My,Rd,y)
上面这个式子成立,是因为左边插板法对应右边 D t D_t Dt d d d选择.
那么有:
∑ t = 0 R ∑ d = 0 t ( t d ) D t ( R , x , y ) ( − 1 ) d \sum_{t=0}^R\sum_{d=0}^t\binom{t}{d}D_t(R,x,y)(-1)^d t=0Rd=0t(dt)Dt(R,x,y)(1)d
= ∑ d = 0 R ( R d ) A ( M x , R − d , x ) A ( M y , R − d , y ) ( − 1 ) d =\sum_{d=0}^R\binom{R}{d}A(M_x,R-d,x)A(M_y,R-d,y)(-1)^d =d=0R(dR)A(Mx,Rd,x)A(My,Rd,y)(1)d
其中:
∑ t = 0 R ∑ d = 0 t ( t d ) D t ( R , x , y ) ( − 1 ) d \sum_{t=0}^R\sum_{d=0}^t\binom{t}{d}D_t(R,x,y)(-1)^d t=0Rd=0t(dt)Dt(R,x,y)(1)d
= ∑ t = 0 R D t ( R , x , y ) ( 1 − 1 ) t = D 0 ( R , x , y ) =\sum_{t=0}^RD_t(R,x,y)(1-1)^t=D_0(R,x,y) =t=0RDt(R,x,y)(11)t=D0(R,x,y)

d p [ x ] [ t ] dp[x][t] dp[x][t] x x x拆分成 t t t个数字,且只能是 K K K个限制中的。
G d ( R , x , y ) G_d(R,x,y) Gd(R,x,y)表示走d个非法向量,走到 ( x , y ) (x,y) (x,y)的方案数。
则: F ( d ) = ∑ x ( R d ) d p [ x ] [ d ] D 0 ( R , T x − x G , T y − x G ) F(d)=\sum_{x}\binom{R}{d}dp[x][d]D_0(R,T_x-xG,T_y-xG) F(d)=x(dR)dp[x][d]D0(R,TxxG,TyxG)
= ∑ t > = d ( t d ) G t ( R , x , y ) =\sum_{t>=d}\binom{t}{d}G_t(R,x,y) =t>=d(dt)Gt(R,x,y)
二项反演有:
G d ( R , x , y ) = ∑ d &lt; = n ( − 1 ) n − d ( n d ) F ( d ) G_d(R,x,y)=\sum_{d&lt;=n}(-1)^{n-d}\binom{n}{d}F(d) Gd(R,x,y)=d<=n(1)nd(dn)F(d)
G 0 ( R , x , y ) = ∑ d &lt; = n ( − 1 ) n F ( d ) G_0(R,x,y)=\sum_{d&lt;=n}(-1)^{n}F(d) G0(R,x,y)=d<=n(1)nF(d)
简单证一下:
已知: F ( n ) = ∑ t &gt; = n ( t n ) f ( t ) F(n) = \sum_{t&gt;=n}\binom{t}{n}f(t) F(n)=t>=n(nt)f(t)
则: ∑ t &gt; = n ( − 1 ) t − n ( t n ) F ( t ) = ∑ t &gt; = n ( − 1 ) t − n ( t n ) ∑ a &gt; = t ( a t ) f ( a ) \sum_{t&gt;=n}(-1)^{t-n}\binom{t}{n}F(t)\\=\sum_{t&gt;=n}(-1)^{t-n}\binom{t}{n}\sum_{a&gt;=t}\binom{a}{t}f(a) t>=n(1)tn(nt)F(t)=t>=n(1)tn(nt)a>=t(ta)f(a)
通常情况下,上面和式不发散。则可以交和次序。
∑ a &gt; = n f ( a ) ∑ t = n a ( − 1 ) t − n ( t n ) ( a t ) \sum_{a&gt;=n}f(a)\sum_{t=n}^{a}(-1)^{t-n}\binom{t}{n}\binom{a}{t} a>=nf(a)t=na(1)tn(nt)(ta)
( t n ) ( a t ) = a ! n ! ( t − n ) ! ( a − t ) ! = a ! ( a − n ! ) ! n ( a − n ) ! ( t − n ) ! ( a − t ) ! = ( a n ) ( a − n t − n ) \binom{t}{n}\binom{a}{t}=\frac{a!}{n!(t-n)!(a-t)!}\\=\frac{a!(a-n!)}{!n(a-n)!(t-n)!(a-t)!}\\=\binom{a}{n}\binom{a-n}{t-n} (nt)(ta)=n!(tn)!(at)!a!=!n(an)!(tn)!(at)!a!(an!)=(na)(tnan)
∑ a &gt; = n f ( a ) ∑ t = n a ( − 1 ) t − n ( t n ) ( a t ) = ∑ a &gt; = n f ( a ) ( a n ) ∑ t = n a ( − 1 ) t − n ( a − n t − n ) = f ( n ) \sum_{a&gt;=n}f(a)\sum_{t=n}^{a}(-1)^{t-n}\binom{t}{n}\binom{a}{t}\\=\sum_{a&gt;=n}f(a)\binom{a}{n}\sum_{t=n}^a(-1)^{t-n}\binom{a-n}{t-n}=f(n) a>=nf(a)t=na(1)tn(nt)(ta)=a>=nf(a)(na)t=na(1)tn(tnan)=f(n)

所以有: F ( n ) = ∑ t &gt; = n ( t n ) f ( t ) F(n) = \sum_{t&gt;=n}\binom{t}{n}f(t) F(n)=t>=n(nt)f(t)可得: f ( n ) = ∑ t &gt; = n ( − 1 ) t − n ( t n ) F ( t ) f(n)=\sum_{t&gt;=n}(-1)^{t-n}\binom{t}{n}F(t) f(n)=t>=n(1)tn(nt)F(t)

/*
 1945555039024054273 = 27*2^56 +1
 
 G = 5
 */
#include <algorithm>
#include <stdio.h>
#include <set>
#include <cmath>
#define MAXN 1000005
#define MAXR 1005
using namespace std;
typedef long long LL;
const int mod = 1e9+7;
const double PI = acos(-1.0);
int P[MAXN];
int Piv[MAXN];
int Mx,My;
void init()
{
    P[0] = 1;
    P[1] = 1;
    Piv[1] = 1;
    for(int i = 2; i < MAXN;i++)
    {
        Piv[i] = mod - (LL)(mod/i)*Piv[mod%i]%mod;
        P[i] = LL(P[i-1])*i%mod;
    }
    for(int i = 2;i < MAXN;i++)Piv[i] = (LL)Piv[i-1]*Piv[i]%mod;
    Piv[0] = 1;
}

inline int getC(int a,int b)
{
    if(b==0)return 1;
    if(a <0)printf("error\n");
    if(b < 0|| b > a)return 0;
    return ((LL)P[a]*Piv[b]%mod)*Piv[a-b]%mod;
}

int tmpK[60];
int dp[MAXR][1005];
int Ax[MAXR][MAXR];
int Ay[MAXR][MAXR];
int Bx[MAXR][MAXR];
int By[MAXR][MAXR];


void CalculateDp(int B, int R, int k)
{
    dp[0][0] = 1;
    for(int i = 1;i<R;i++)
    {
        for(int j = 0;j<B;j++)
        {
            for(int t = 0;t < k; t++)
            {
                if(j<tmpK[t])continue;
                dp[j][i] +=dp[j-tmpK[t]][i-1];
                if(dp[j][i]>=mod)dp[j][i] -=mod;
            }
        }
    }
}

int CalcD(int R,int x,int y)
{
    if(R<0)return 0;
    int ans = 0;
    for(int i=0;i<=R;i++)
    {
        int u = (LL)getC(R,i)*Ax[R-i][x]%mod;
        u = (LL)u*Ay[R-i][y]%mod;
        if(i&1)u = (mod - u)%mod;
        ans += u;
        if(ans >= mod)ans -= mod;
    }
    return ans;
}

// 5 5 4 4 2 1 3 1 2 3
//5 5 4 4 2 1 2 1 2


int main ()
{
    init();
    int Tx, Ty, R, G, k;
    scanf("%d %d %d %d",&Tx, &Ty, &Mx, &My);
    scanf("%d %d", &R, &G);
    scanf("%d", &k);
    int B = min(Tx,Ty)/G + 1;
    for(int i = 0;i<k;i++)
    {
        scanf("%d",tmpK + i);
        tmpK[i] /= G;
    }
    sort(tmpK, tmpK + k);
    B = min(B, tmpK[k-1]*R+1);

    for(int i=0;i<=R;i++)
    {
        for(int x = 0;x< B;x++)
        {
            int offset = x*G;
            for(int a =0,X = Tx - offset ;a <= i;a++)
            {
                int b = X - (Mx +1)*a;
                if(b<0)break;
                LL u = (LL)getC(i,a)*getC(i+b-1,b)%mod;
                if(a&1) Ax[i][x] += (mod - u)%mod;
                else Ax[i][x] += u;
                if(Ax[i][x] >=mod)Ax[i][x] -= mod;
            }
            for(int a=0,Y = Ty - offset;a <=i;a++)
            {
                int b = Y - (My +1)*a;
                if(b<0)break;
                LL u = (LL)getC(i,a)*getC(i+b-1,b)%mod;
                if(a&1) Ay[i][x] += (mod - u)%mod;
                else Ay[i][x] += u;
                if(Ay[i][x] >=mod)Ay[i][x] -= mod;
            }
        }
    }
    int ans = 0;
    if(k == 0)
    {
        printf("%d\n",CalcD(R,0,0));
        return 0;
    }
    CalculateDp(B,R+1,k);
    int limR = min(Tx,Ty)/(tmpK[0]*G) + 1;
    //printf("%d ^^^^^\n",CalcD(2,3,3));
    for(int d = 0;d< limR;d++)
    {
        int u = 0;
        for(int x = 0;x<B;x++)
        {
            u += ((LL)getC(R,d)*dp[x][d]%mod)*CalcD(R-d,x,x)%mod;
            if(u>=mod)u-=mod;
        }
        if(d&1)
            u = (mod - u)%mod;
        ans = (ans + u)%mod;
    }
    printf("%d\n",ans);
}



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值