matrix

【from new_dtoj 3968: matrix】
题目描述
小z 的女朋友送给小z 一个n×n的矩阵。但是矩阵实在太大了,小z 的女朋友拿不动,只能带给他两个长度为n 的整数序列l,t,分别作为矩阵F的第一行和第一列(保证l1=t1),并且告诉小z 矩阵可以通过如下方式得到:Fi,j=a∗Fi,j−1+b∗Fi−1,j
现在小z 猜到了系数a,b,他想要计算Fn,n模109+7{10^9+7}的值。
输入
第一行三个整数n,a,b。
第二行n个数表示t。
第三行n个数表示l。
输出
一行一个整数表示答案。
样例输入
4 3 5
4 1 7 3
4 7 4 8
样例输出
59716
提示
对于前40%的数据,n≤5000;
对于另外20%的数据,a=0;
对于100%的数据,n,a,v,lil_i,tit_i10510^5
题解:
明显Fn,nFn,n与除(1,1)外的第一行和第一列的每个数有关,即Fn,n=AxFn,n=\sum A*x(x是第一行和第一列的每个数的数值,A是其系数)
考虑怎么求系数,可以发现每次向右则乘a ,向下则乘b,总共的贡献就是累乘的数*从该点到右下角的路径数(即蚂蚁路径)
对于tit_iA=(n22ni2)anibn1A={(^{2n-i-2}_{n-2})}*a^{n-i}*b^{n-1}
对于lil_iA=(n22ni2)an1bniA={(^{2n-i-2}_{n-2})}*a^{n-1}*b^{n-i}
代码如下

#include <cstdio>
#include <string>
#define _(d) while(d(isdigit(c=getchar())))
using namespace std;
inline int R(){
	int x,f=1;char c;_(!)c=='-'?f=0:f;x=(c^48);
	_()x=(x<<3)+(x<<1)+(c^48);return f?x:-x;
}
const int P=1e9+7,N=1e5+5;
int n,a,b,l[N],t[N],ap,bp,pa=1,pb=1,jc[N*2],ny[N*2],ans,t1,t2;
//ap是a^(n-1),pa是a的累乘,b类同
//t1,t2是组合数的系数 
inline int K(int x,int y){
	int A=1;
	while(y){
		if (y&1) A=1ll*A*x%P;
		x=1ll*x*x%P;y>>=1;
	}
	return A;
}
inline int C(int x,int y){return 1ll*jc[x]*ny[y]%P*ny[x-y]%P;}
int main(){
	n=R();a=R();b=R();ap=K(a,n-1);bp=K(b,n-1);
	for (int i=1;i<=n;i++) l[i]=R();
	for (int i=1;i<=n;i++) t[i]=R();
	if (n==1){printf("%d\n",l[1]%P);return 0;}
	t1=n-2;jc[0]=1;for (int i=1;i<=n*2;i++) jc[i]=1ll*jc[i-1]*i%P;
	ny[n*2]=K(jc[n*2],P-2);for (int i=n*2;i;i--) ny[i-1]=1ll*ny[i]*i%P;
	for (int i=n;i>1;i--,t1++,t2++,pa=1ll*pa*a%P,pb=1ll*pb*b%P)
		ans=((1ll*ans+1ll*l[i]*ap%P*pb%P*C(t1,t2)%P)%P+1ll*t[i]*bp%P*pa%P*C(t1,t2)%P)%P;
	return printf("%d\n",ans),0;
}
posted @ 2018-10-18 18:39  xjqxjq  阅读(335)  评论(0编辑  收藏  举报