小z 的女朋友送给小z 一个n×n的矩阵。但是矩阵实在太大了,小z 的女朋友拿不动,只能带给他两个长度为n 的整数序列l,t,分别作为矩阵F的第一行和第一列(保证(l_1=t_1)),并且告诉小z 矩阵可以通过如下方式得1:
(F(i,j)=a*F(i,j-1)+b*F(i-1,j))
现在小z 猜到了系数a,b,他想要计算F(n,n)模1e9+7的值。
样例输入
4 3 5
4 1 7 3
4 7 4 8
样例输出
59716
提示
对于前40%的数据,n≤5000;
对于另外20%的数据,a=0;
对于100%的数据,(n,a,v,l_i,t_ile10^5)
题解:很明显F(n,n)与除(1,1)外第一行和第一列的每个数有关,手膜可得点(x1,y1)对(x2,y2)的贡献为
(a^{x_2-x_1}*b^{y_2-y_1}* (x_1,y_1)(x_2,y_2))之间的路径条数
(0,0)到(n,m)的路径条数为(n+m choose m)( 只往右或往下走) 注意数组开两倍
[F(n,n)=sum A*x(x是第一行和第一列的每个数的数值,A是其系数) \
对于t_i,A={2n-i-2 choose n-2}*a^{n-i}*b^{n-1}\
对于l_i,A={2n-i-2 choose n-2}*a^{n-1}*b^{n-i}
]
代码: 明天再放 咕咕咕 没码完
#include<cstdio>
#define maxn 100001
#define int long long
const int mod=1e9+7;
using namespace std;
int n,a,b,l[maxn],t[maxn],ap,bp,pa=1,pb=1,jc[maxn<<1],ny[maxn<<1],ans=0,t1,t2;
//ap是a^(n-1),pa是a的累乘,b同 jc阶乘 ny逆元
//t1,t2是组合数的系数
int qpow(int a,int b){
int az=1,base = a % mod;
if(b == 0) return 1;
while(b){
if(b & 1) az = az * base % mod;
base = base * base % mod;
b >>= 1;} return az;}
inline int C(int x,int y){return jc[x]*ny[y]%mod*ny[x-y]%mod;}
signed main(){
scanf("%d%d%d",&n,&a,&b);
ap=qpow(a,n-1);bp=qpow(b,n-1);
for(int i=1;i<=n;i++) scanf("%d",&l[i]);
for(int i=1;i<=n;i++) scanf("%d",&t[i]);
if(n == 1) {printf("%d
",l[1]%mod);return 0;}
t1 = n-2; jc[0] = 1;
for(int i=1;i <= (n<<1);i++) jc[i] = jc[i-1] * i % mod;
ny[n*2] = qpow(jc[n*2],mod - 2);
for(int i=(n<<1);i;i--)
ny[i-1] = ny[i] * i % mod;
for(int i=n;i>1;i--,t1++,t2++,pa = pa*a%mod,pb = pb*b%mod)
ans=((ans + l[i]*ap % mod* pb%mod *C(t1,t2)%mod) + (t[i]*bp%mod*pa%mod*C(t1,t2)%mod))%mod;
printf("%d",ans);
return 0;
}