BZOJ3260 Jump【Number of Combinations】

topic

Cults like to jump in all kinds of spaces. Now, the cult has come to a two-dimensional plane.
In this plane, if the cult currently jumps to (x,y), then he can choose to jump to the following 4 points in the next step:
(x-1,y),(x+1,y),(x,y- 1), (x, y+1).
And whenever the cult reaches a point, he needs to consume some physical strength,
assuming that the physical strength required to reach (x, y) is represented by C(x, y).
For C(x,y), there are the following properties:
1. If x=0 or y=0, then C(x,y)=1.
2. If x>0 and y>0, then C(x,y)=C(x,y-1)+C(x-1,y).
3. If x<0 and y<0, then C(x,y)=infinity.
Now, the cult wants to know how much stamina it takes to start from (0,0) to (N,M), and the stamina
to get to (0,0) also needs to be counted).
Since the answer may be large, just output the answer modulo 10^9+7.

input format

Read in two integers N, M, representing the point the cult wants to reach.
0<=N, M<=10^12 , N*M<=10^12

output format

The output is only an integer, which represents the result of modulo 10^9+7 by the minimum physical effort that the cult needs to spend.

input sample

1 2

Sample output

6

answer

Draw a picture and find that it is a Yanghui triangle

First make \(M \le N\)
we have to go to \({N + M \choose M}\)
greedy path is to go first \(N + 1\) \ (1\) , and then go diagonally \(M\) step
Try to change the path and find that there is no problem with such greed

The answer is
\[N + \sum\limits_{i = 0}^{M} {N + i \choose i}\]
The number of combinations has a more commonly used conclusion is
\[\sum\limits_{i = 0}^ {M} {N + i \choose i} = {N + M + 1 \choose M}\]
It can be proved by recursion of combinatorial numbers

Then the answer is
\[N + {N + M + 1 \choose M}\]
Since the title has the limitation of \(N*M \le 10^{12}\) , so \(M \le 10^6\) , just calculate

#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;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325087040&siteId=291194637