【HDU】5490 Simple Matrix(2015 ACM/ICPC Asia Regional Hefei Online)

66 篇文章 0 订阅
11 篇文章 0 订阅

Simple Matrix


题目链接


题目大意

    给你一个矩阵,n行m列, Cn,m=Cn1,m+Cn,m1 ,第0行是一个等比数列,第0列是一个等差数列,现在让你求 Cn,m


题解

组合数学

    首先想到求 Cn,m 的话,分别求等差在 Cn,m 的和,以及等比在 Cn,m 的和,关于等差,把表画出来后可以看到每一项的系数都是一个斜着的杨辉三角,然后我们写出每一项的系数,我们可以把等差的和表示出来:

suman,m=i=1n(Cnin+mi1Ai)

    同样的,可以求出等比的和:
sumbn,m=i=1m(Cmin+mi1Bi)

    可以看到等差我们可以直接求出,而等比因为m太大,无法直接求,所以另想办法:

0 b1 b2 b3
0 b1 b1+b2 b1+b2+b3
0 b1 2b1+b2 3b1+2b2+b3
0 b1 3b1+b2 6b1+3b2+b3

    可以看到, Cn,m 中b的和其实是上一行前m项的和,于是我们用 Si,j 表示第i行前j项的和:

sumbn,m=Sn1,m

    写出S前几项:
S0,m=b1(1qm)1q

S1,m=S0,1+S0,2+...+S0,m

S1,m=mb1(b1q+b1q2+b1q3+...+b1qm)1q

q:

S1,m=mb1qS0,m1q

    我们还可以继续求 S2,m
S2,m=(1+2+3+...+m)b1qS1,m1q

    可以看到目前我们比较难处理的就是 b1 前面的系数,我们可以发现它跟S很像,每次都是一个和式再求和,不过好在这个系数比较好表示,我们将它写出来后发现 b1 的系数也是一个杨辉三角,将其表示后:
b1=Cnn+m1

    到这里,我们写出 Sn,m
Sn,m=qSn1,mCnn+m1b1q1

    可以发现我们可以推出 Sn,m ,至此,问题解决。


代码

    这个代码无法解决(0,0)(0,m)(n,0)的情况….本来后来改了,但是那个代码太丑,就不发了..

#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
#define MOD 1000000007
#define maxn 10005

using namespace std;

LL T,b,q,a,d,n,m,inv[maxn];

LL pow_mod(LL a,LL b)
{
    LL ans=1;
    while (b)
    {
        if (b&1) ans=(ans*a)%MOD;
        b>>=1;
        a=(a*a)%MOD;
    }
    return ans;
}

LL C(LL n,LL m)
{
    if (n>m) return 0;
    LL p=min(n,m-n),ans=1;
    for (int i=1;i<=p;i++) ans=(ans*(m-i+1)%MOD*inv[i])%MOD;
    return ans;
}

int main()
{
    int Case=1;
    for (int i=1;i<=maxn;i++) inv[i]=pow_mod(i,MOD-2);
    scanf("%I64d",&T);
    while (T--)
    {
        scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&b,&q,&a,&d,&n,&m);
        LL t=C(n-1,n+m-2),suma=0,summ=0,A=a,B=b;
        LL invq=pow_mod(q-1,MOD-2);
        //suma
        for (LL i=1;i<=n;i++)
        {
            suma=(suma+t*A)%MOD;
            A=(d+A)%MOD;
            t=(t*(n-i)%MOD*pow_mod(n+m-i-1,MOD-2))%MOD;
        }
        //summ
        t=1; summ=(b*pow_mod(q,m-1))%MOD;
        for (LL i=0;i<=n-1;i++)
        {
            summ=((q*summ-t*b%MOD)%MOD *invq)%MOD;
            t=(t*(i+m)%MOD*inv[i+1])%MOD;
        }
        printf("Case #%d: %I64d\n",Case++,((suma+summ)%MOD+MOD)%MOD );
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值