jzoj 4709. 【NOIP2016提高A组模拟8.17】Matrix 组合数+乘法逆元

来源:互联网 发布:java websocket客户端 编辑:程序博客网 时间:2024/05/19 23:02

题意:有一个n*n的矩阵,给出矩阵的第一行和第一列数字,对于矩阵的其他位置f[i,j]=a*f[i,j-1]+b*f[i-1,j]

求f[n,n] mod 1000000007

n<=100000


分析:直接递推很明显不可能,那么我们就可以改成统计第一行和第一列的每个元素对答案的贡献。

那么第一行第i个元素也就是t[1,i]对答案的贡献为C(2n−i−2,n−2)*a[n−i]*b[n−1]*t[1,i]

对于求组合数,我们用乘法逆元就好了。

逆元一般用扩展欧几里得算法来求得,如果为素数,那么还可以根据费马小定理得到逆元为


代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 200005#define ll long long#define MOD 1000000007using namespace std;ll a,b,mia[N],mib[N],mi,ny[N],c[N];int n,l[N],h[N];int ksm(int x){if (!x) return 1;if (x==1) return mi;int s=ksm(x/2);s=(ll)s*s%MOD;if (x%2==1) s=s*mi%MOD;return s;}int main(){scanf("%d%d%d",&n,&a,&b);for (int i=1;i<=n;i++)scanf("%d",&l[i]);for (int i=1;i<=n;i++)scanf("%d",&h[i]);c[1]=1;mia[0]=1;mia[1]=a;mib[0]=1;mib[1]=b;ny[1]=1;ny[0]=1;for (int i=2;i<=n*2;i++){c[i]=c[i-1]*i%MOD;mi=c[i];ny[i]=ksm(MOD-2);mia[i]=mia[i-1]*a%MOD;mib[i]=mib[i-1]*b%MOD;}ll ans=0;for (int i=2;i<=n;i++){ans=(ans+(ll)c[2*n-i-2]*ny[n-2]%MOD*ny[n-i]%MOD*mia[n-i]%MOD*mib[n-1]%MOD*h[i]%MOD)%MOD;ans=(ans+(ll)c[2*n-i-2]*ny[n-2]%MOD*ny[n-i]%MOD*mia[n-1]%MOD*mib[n-i]%MOD*l[i]%MOD)%MOD;}printf("%lld",ans);}


0 0