标准的带限制条件的非降路径问题,从 (1,1) 到 (N,N) 的“非降路径”不能经过对角线。
证明见-离散课本P.199
因为n的数量级太大,所以要用Lucas定理。此处代码参考自,,忘了,exgcd
/*
Lucas¶¨Àí
C(m+n,m)%p
Exe.Time 733MS
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll Mod = 10007;
ll pow_mod(ll a,ll b,ll mod)
{
ll ans = 1;
a %= mod;
while(b)
{
if(b&1)
ans = ans * a % mod;
b >>= 1;
a = a*a%mod;
}
return ans;
}
ll GetC(ll n,ll m,ll mod)
{
if(m > n)
return 0;
if(m > n - m)
m = n - m;
ll a = 1,b = 1;
while(m)
{
a = a*n%mod;
b = b*m%mod;
m--;
n--;
}
return a * pow_mod(b,mod-2,mod)%mod;
}
ll Lucas(ll n,ll k,ll mod)
{
if(k == 0)
return 1;
return GetC(n%mod,k%mod,mod)*Lucas(n/mod,k/mod,mod)%mod;
}
void Exgcd(ll a, ll b, ll &x, ll &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
ll x1, y1;
Exgcd(b, a%b, x1 ,y1);
x = y1;
y = x1 - (a/b)*y1;
}
int main()
{
ll n,x,y;
while(scanf("%lld",&n) != EOF)
{
Exgcd(n,Mod,x,y);
x = (x%Mod + Mod) % Mod;
x <<= 1ll;
ll ans = Lucas(n*2-2,n-1,Mod);
ans = ans * x % Mod;
printf("%lld\n",ans);
}
return 0;
}
从(0,0)到(n,m)的带限制的非降路径
“玲珑杯”ACM比赛 Round #4 D
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1000005;
const int MOD;
typedef long long LL;
LL n,m,p;
LL f[N];
LL gcd(LL a,LL b) {return b ? gcd(b,a%b) : a;}
LL lcm(LL a,LL b) {return a / gcd(a,b) * b;}
void Init(LL p)
{
f[0] = 1;
for(int i = 1;i <= p;i++)
f[i] = (f[i-1]*i) % p;
}
LL pow_mod(LL a,LL b,LL MOD)
{
LL ans = 1;
while(b)
{
if(b%2)
ans = ans*a%MOD;
a = a*a%MOD;
b /= 2;
}
return ans;
}
LL Lucas(LL n,LL m,LL p)
{
LL ans = 1;
while(n && m)
{
LL a = n%p,b = m%p;
if(a < b)
return 0;
ans = (ans*f[a]*pow_mod(f[b]*f[a-b]%p,p-2,p))%p;
n /= p;m /= p;
}
return ans;
}
int main()
{
int t;
cin >> t;
LL n,m;
while(t--)
{
Init(10007);
scanf("%lld%lld",&n,&m);
if(m == 0)
{
puts("1");
continue;
}
printf("%lld\n",(Lucas(m+n,m,MOD)-Lucas(m+n,m-1,MOD)+LL(MOD))%LL(MOD));
}
return 0;
}
官方题解卡特兰数推得
链接