2.矩阵(matrix.c/matrix.cpp/matrix.pas)
【题目背景】
std热爱计算机,std的妹子热爱数学(假的吧)
有一天,他们在一起讨论功课时,她留给了他一个问题。
std看完后发现自己好菜啊,竟然不会(QwQ)
于是他又找到了你······
【题目描述】
这个问题是这样的:
有这样一个矩阵a(如下表)
显而易见的是矩阵的第一行、第一列均为1,中间的数a(i,j)=a(i-1,j)+a(i,j-1)。
现在你要求出。
【输入输出格式】
【输入格式】
输入的第一行有两个正整数n,m。
【输出格式】
输出一行,为。
【输入输出样例】
【输入#1】
1 1
【输出#1】
1
【输入#2】
3 2
【输出#2】
9
【提示】
共25组数据。
对于16%的数据,1<=n,m<=100。
对于24%的数据,1<=n,m<=1000。
对于40%的数据,1<=n,m<=10000。
对于48%的数据,1<=n,m<=100000。
对于56%的数据,1<=n,m<=1000000。
对于68%的数据,1<=n,m<=10000000。
对于100%的数据,1<=n,m<=25000000。
另外,对于12%的数据,m=n。
算法:组合数+乘法逆元(线性筛)(我复习了一下lucas定理)
题解:
乱搞,打表,找规律。
附上官方题解:
我们来看一下这个矩阵:
1 1 1 1
1 2 3 4
1 3 6 10
1 4 10 20
1 5 15 35
我们会发现:
1+1+1=3
1+2+3=6
1+3+6=10
1+4+10=15
...
1+1+1+1=4
1+2+3+4=10
1+3+6+10=20
...
...
即sum(a(i,1),...,a(i,j))=a(i+1,j)(这个由递推式是可证的)
因此所求就是sum(a(2,m),a(3,m),...a(n+1,m))
即sum(a(1,m),a(2,m),a(3,m),...a(n+1,m))-a(1,m+1)
=a(n+1,m+1)-1
这不就是个组合数吗?????(C(n+m,n)-1)
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#define ll long long
#define N 25000005
using namespace std;
const ll p=1050307103;
int n,m;
ll inv[N];
void ny()
{
inv[0]=1;
inv[1]=1;
for(int i = 2;i <= n+m;i++)
{
inv[i]=(p-p/i)*inv[p%i]%p;
}
}
ll jc[N];
ll lucas(int x,int y)
{
if(x<y) return 0;
else if(x<p) return ((jc[x]*inv[y])%p*inv[x-y])%p;
else return lucas(x/p,y/p)*lucas(x%p,y%p)%p;
}
int main()
{
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
scanf("%d%d",&n,&m);
ny();
jc[0]=1,jc[1]=1;
for(int i = 2;i <= n+m;i++)
{
jc[i]=jc[i-1]*i%p;
}
for(int i = 2;i <= n+m;i++)
{
inv[i]=(inv[i]*(inv[i-1]%p))%p;
}
printf("%I64d\n",lucas(n+m,n)-1);
return 0 ;
}