matrix
题目描述
小z 的女朋友送给小z 一个n×nn×n的矩阵。但是矩阵实在太大了,小z 的女朋友拿不动,只能带给他两个长度为nn 的整数序列l,tl,t,分别作为矩阵FF的第一行和第一列(保证l1=t1l1=t1),并且告诉小z 矩阵可以通过如下方式得到:
Fi,j=a∗Fi,j−1+b∗Fi−1,jFi,j=a∗Fi,j−1+b∗Fi−1,j
现在小z 猜到了系数a,ba,b,他想要计算Fn,nFn,n模109+7109+7的值。
输入
第一行三个整数n,a,bn,a,b。
第二行nn个数表示tt。
第三行nn个数表示ll。
输出
一行一个整数表示答案。
样例输入
<span style="color:#333333"><span style="color:#333333">4 3 5
4 1 7 3
4 7 4 8</span></span>
样例输出
<span style="color:#333333"><span style="color:#333333">59716</span></span>
提示
对于前40%40%的数据,n≤5000n≤5000;
对于另外20%20%的数据,a=0a=0;
对于100%100%的数据,n,a,v,li,tin,a,v,li,ti。
来源
手推几个小样例可以发现
点(x1,y1)对(x2,y2)的贡献为
a^(x2-x1)*b^(y2-y1)* (x1,y1,x2,y2)之间的路径条数
(0,0)到(n,m)的路径条数为C(n+m,m)( 只往右或往下走)
那就是组合数了
注意数组要开2倍
还有要取模!!
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 200005
#define ll long long
#define mod 1000000007
using namespace std;
int n,x[maxn],y[maxn];
ll a,b,ans,h[maxn],ny[maxn];
ll work(ll t,int num){
ll p=t,ans=1;
while(num){
if(num&1)ans=ans*p;
p=p*p;p%=mod;ans%=mod;num/=2;
}
return ans;
}
ll C(int M,int N){
ll ls=h[N]*ny[M];ls%=mod;
ls=ls*ny[N-M];ls%=mod;
return ls;
}
int main()
{
cin>>n>>b>>a;
for(int i=1;i<=n;i++)scanf("%d",&x[i]);
for(int i=1;i<=n;i++)scanf("%d",&y[i]);
int nn=n+n;
h[0]=1;for(int i=1;i<=nn;i++)h[i]=(i*h[i-1])%mod;
ny[nn]=work(h[nn],mod-2);
for(int i=nn-1;i>=0;i--)ny[i]=(ny[i+1]*(i+1))%mod;
ll tb=1,ta=1,now=1;
for(int i=2;i<=n;i++)tb=(tb*b)%mod,ta=(ta*a)%mod;
for(int i=n;i>=2;i--){
ll tmp=x[i]*tb;tmp%=mod;
tmp=tmp*now;tmp%=mod;
tmp=tmp*C(n-i,n-2+n-i);tmp%=mod;
//cout<<i<<' '<<now<<' '<<tmp<<' '<<n-i<<' '<<n-2+n-i<<endl;
ans=ans+tmp;ans%=mod;
now=now*a;now%=mod;
}
now=1;
for(int i=n;i>=2;i--){
ll tmp=y[i]*ta;tmp%=mod;
tmp=tmp*now;tmp%=mod;
tmp=tmp*C(n-i,n-2+n-i);tmp%=mod;
ans=ans+tmp;ans%=mod;
now=now*b;now%=mod;
}
cout<<ans<<endl;
return 0;
}