证明步骤:使用组合数公式进行拆解并通分,即可得到。这个公式有条件,就是n,m>0且n>m
代码
#include
using namespace std;
#define MOD 1000000007
long long arr[1001][1001];
int main(){
for(int i = 0;i<=1000;i++){
for(int j = 0;j<=i;j++){
if(j==0||i==j)arr[i][j] = 1;
else{
arr[i][j] = (arr[i-1][j-1] + arr[i-1][j])%MOD;
}
}
}
printf("%lld\n",arr[500][222]);
return 0;
}
但是有不足的是,对于n较大m较大时,时间复杂度不允许,是n^2级别,因此此时可以用逆元方式求解
代码有空贴下。
欧几里得是数论中十分重要的一个,我们主要用到其辗转相除求最大公约数。在这里我省略欧几里德算法。讲扩展的欧几里德。
首先知道ax+by=c这个算式,即确定a和b,如果a % b = c那么在这个方程里肯定是有解的,于是我们对其进行扩展。即,根据ax = 1(mod b)这个算法,我们结合其算式,能求出x,即a的逆。
于是我们就能得到这样的算式:
ax1 + by1 = gcd(a,b)
bx2 + (a%b)y2 = gcd(b,a%b)
我们根据欧几里德算法可知gcd(a,b)和gcd(b,a%b)是一样的
ax1 + by1 = gcd(a,b)
bx2 + (a%b)y2 = gcd(a,b)
现在问题如何求解 x2,y2
我们直接得出ax1+by1 = bx2 + (a%b)y2
ax1+by1 = bx2 + (a-a/b*b)y2
ax1+by1 = ay2 + b(x2 -a/b)
x1 = y2
y1 = (x2 -y2a/b)
我们可以清楚的看到,由后面可以推出前面的式子,当然gcd最后会b=0此时ax+by=1时,令x=1,b=任意数,然后进行逆推,推到初始的a和b的方程,x和y就是最简单的解。当然求逆元时,x有时候会为负数,这时需要(x+mod)%mod进行正数取模,保证x为正整数解。
一下为代码,参考其他人的,写的非常简洁,而且能判断时候互质
typedef long long ll;
void extgcd(ll a,ll b,ll& d,ll& x,ll& y){
if(!b){ d=a; x=1; y=0;}
else{ extgcd(b,a%b,d,y,x); y-=x*(a/b); }
}
ll inverse(ll a,ll n){
ll d,x,y;
extgcd(a,n,d,x,y);
return d==1?(x+n)%n:-1;
}