BZOJ3260 跳 【組合數】
題目
邪教喜歡在各種各樣空間內跳。現在,邪教來到了一個二維平面。
在這個平面內,如果邪教當前跳到了(x,y),那麽他下一步可以選擇跳到以下4個點:
(x-1,y),(x+1,y),(x,y-1),(x,y+1)。
而每當邪教到達一個點,他需要耗費一些體力,
假設到達(x,y)需要耗費的體力用C(x,y)表示。
對於C(x,y),有以下幾個性質:
1、若x=0或者y=0,則C(x,y)=1。
2、若x>0且y>0,則C(x,y)=C(x,y-1)+C(x-1,y)。
3、若x<0且y<0,則C(x,y)=無窮大。
現在,邪教想知道從(0,0)出發到(N,M),最少花費多少體力
到達(0,0)點花費的體力也需要被算入)。
由於答案可能很大,只需要輸出答案對10^9+7取模的結果。
輸入格式
讀入兩個整數 N ,M,表示邪教想到達的點。
0<=N, M<=10^12 ,N*M<=10^12
輸出格式
輸出僅一個整數,表示邪教需要花費的最小體力對 10^9+7取模的結果。
輸入樣例
1 2
輸出樣例
6
題解
畫一下圖就發現是一個楊輝三角
先使\(M \le N\)
我們要走到\({N + M \choose M}\)
貪心一下路徑就是先走\(N + 1\)個\(1\),再斜著走\(M\)步
嘗試改變一下路徑就發現這樣的貪心沒有問題
答案就是
\[N + \sum\limits_{i = 0}^{M} {N + i \choose i}\]
組合數有一個比較常用的結論就是
\[\sum\limits_{i = 0}^{M} {N + i \choose i} = {N + M + 1 \choose M}\]
由組合數遞推可證明
那麽答案就是
\[N + {N + M + 1 \choose M}\]
由於題目有\(N*M \le 10^{12}\)的限制,所以\(M \le 10^6\),直接算就好了
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<‘ ‘; puts("");
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000,P = 1e9 + 7;
LL N,M;
LL qpow(LL a,LL b){
LL ans = 1;
for (; b; b >>= 1,a = a * a % P)
if (b & 1) ans = ans * a % P;
return ans;
}
int main(){
scanf("%lld%lld",&N,&M);
if (M > N) swap(N,M);
LL ans = 1,ansb = 1;
for (LL i = 1; i <= M; i++){
ans = ans * ((N + M + 2 - i + P) % P) % P;
ansb = ansb * i % P;
}
ans = ((ans * qpow(ansb,P - 2) % P + N) % P + P) % P;
printf("%lld\n",ans);
return 0;
}
BZOJ3260 跳 【組合數】