链接
https://nanti.jisuanke.com/t/28869
题解
我看的题解:https://blog.csdn.net/MIECZ/article/details/80591212
有个问题他没说,就是每种不合法方案如何与已经统计的方案构造一一对应关系?
只有你构造出了一一对应关系,才能相减,因为这个减法的实质是从一个全集中减去一个子集
令
A=Cn−2n+m−4Cm−2n+m−4
A
=
C
n
+
m
−
4
n
−
2
C
n
+
m
−
4
m
−
2
,
B=Cn−1n+m−4Cm−1n+m−4
B
=
C
n
+
m
−
4
n
−
1
C
n
+
m
−
4
m
−
1
答案
ans=A−B
a
n
s
=
A
−
B
对于一种在
A
A
中存在的,路线相交的方案,我考虑图形相同的方案集合,这个集合中,我选择最后一个交点,调换两条路径的走向,那么就能够构造出一种在中统计过的方案,而且这样肯定能够构造出
B
B
中符合这种图形的全部方案。
既然对于每种图形,它在和
B
B
<script type="math/tex" id="MathJax-Element-1250">B</script>中对应的路径数相同,所以相减也就没问题了
这题其实最后减去的不是子集,但是构造出一种和子集一一对应的路径集合,这也是很巧妙了
代码
//组合数
#include <cstdio>
#include <algorithm>
#include <cctype>
#include <cstring>
#define maxn 2018
#define ll long long
#define mod 1000000007ll
using namespace std;
ll frac[maxn], _frac[maxn], N, M, f[maxn];
ll fastpow(ll a, ll b)
{
ll t, ans=1;
for(t=a;b;b>>=1,t=t*t%mod)if(b&1)ans=ans*t%mod;
return ans;
}
ll C(ll n, ll m)
{
return frac[n]*_frac[m]%mod*_frac[n-m]%mod;
}
void init()
{
ll i, j;
frac[0]=_frac[0]=1;
for(i=1;i<=2000;i++)frac[i]=frac[i-1]*i%mod, _frac[i]=fastpow(frac[i],mod-2);
}
int main()
{
ll ans;
init();
while(~scanf("%lld%lld",&N,&M))
{
if(N==2 or M==2)ans=1;
else ans=C(N+M-4,M-2)*C(N+M-4,N-2)%mod-C(N+M-4,M-1)*C(N+M-4,N-1)%mod;
printf("%lld\n",(ans%mod+mod)%mod);
}
return 0;
}