Simple Matrix
题目链接
题目大意
给你一个矩阵,n行m列, Cn,m=Cn−1,m+Cn,m−1 ,第0行是一个等比数列,第0列是一个等差数列,现在让你求 Cn,m
题解
组合数学
首先想到求
Cn,m
的话,分别求等差在
Cn,m
的和,以及等比在
Cn,m
的和,关于等差,把表画出来后可以看到每一项的系数都是一个斜着的杨辉三角,然后我们写出每一项的系数,我们可以把等差的和表示出来:
suman,m=∑i=1n(Cn−in+m−i−1∗Ai)
同样的,可以求出等比的和:
sumbn,m=∑i=1m(Cm−in+m−i−1∗Bi)
可以看到等差我们可以直接求出,而等比因为m太大,无法直接求,所以另想办法:
0 | b2 | b3 | |
---|---|---|---|
0 | b1+b2 | b1+b2+b3 | |
0 | 2b1+b2 | 3b1+2b2+b3 | |
0 | 3b1+b2 | 6b1+3b2+b3 |
可以看到,
Cn,m
中b的和其实是上一行前m项的和,于是我们用
Si,j
表示第i行前j项的和:
sumbn,m=Sn−1,m
写出S前几项:
S0,m=b1(1−qm)1−q
S1,m=S0,1+S0,2+...+S0,m
写出来S1,m=mb1−(b1q+b1q2+b1q3+...+b1qm)1−q
可以看到后面那个求和的项可以提一个q出来,然后有:
S1,m=mb1−qS0,m1−q
我们还可以继续求 S2,m
S2,m=(1+2+3+...+m)b1−qS1,m1−q
可以看到目前我们比较难处理的就是 b1 前面的系数,我们可以发现它跟S很像,每次都是一个和式再求和,不过好在这个系数比较好表示,我们将它写出来后发现 b1 的系数也是一个杨辉三角,将其表示后:
b1系数=Cnn+m−1
到这里,我们写出 Sn,m
Sn,m=qSn−1,m−Cnn+m−1b1q−1
可以发现我们可以推出 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;
}