Problem:


Score : 600 points

Problem Statement

Snuke is standing on a two-dimensional plane. In one operation, he can move by 1 in the positive x-direction, or move by 1 in the positive y-direction.

Let us define a function f(r, c) as follows:

f(r,c) :=  (The number of paths from the point (0, 0) to the point (r, c) that Snuke can trace by repeating the operation above)

Given are integers r_1, r_2, c_1, and c_2.
Find the sum of f(i, j) over all pair of integers (i, j) such that r_1 ≤ i ≤ r_2 and c_1 ≤ j ≤ c_2, and compute this value modulo (10^9+7).

Constraints

1 ≤ r_1 ≤ r_2 ≤ 10^6

1 ≤ c_1 ≤ c_2 ≤ 10^6

All values in input are integers.

Input

Input is given from Standard Input in the following format:

r_1 c_1 r_2 c_2

Output

Print the sum of f(i, j) modulo (10^9+7).

Sample Input 1

1 1 2 2

Sample Output 1

14

For example, there are two paths from the point (0, 0) to the point (1, 1): (0,0) → (0,1) → (1,1) and (0,0) → (1,0) → (1,1), so f(1,1)=2.

Similarly, f(1,2)=3, f(2,1)=3, and f(2,2)=6. Thus, the sum is 14.

Sample Input 2

314 159 2653 589

Sample Output 2

602215194



Sample input:
1 1 2 2


Sample output:
14

Submission status: Accepted

Solution code:
import sys,collections as cl,bisect as bs
sys.setrecursionlimit(100000)
input = sys.stdin.readline
mod = 10**9+7
Max = sys.maxsize
def l(): #intのlist
  return list(map(int,input().split()))
def m(): #複数文字
  return map(int,input().split())
def onem(): #Nとかの取得
  return int(input())
def s(x): #圧縮
  a = []
  if len(x) == 0:
    return []
  aa = x[0]
  su = 1
  for i in range(len(x)-1):
    if aa != x[i+1]:
      a.append([aa,su])
      aa = x[i+1]
      su = 1
    else:
      su += 1
  a.append([aa,su])
  return a
def jo(x): #listをスペースごとに分ける
  return " ".join(map(str,x))
def max2(x): #他のときもどうように作成可能
  return max(map(max,x))
def In(x,a): #aがリスト(sorted)
    k = bs.bisect_left(a,x)
    if k != len(a) and a[k] ==  x:
        return True
    else:
        return False

def pow_k(x, n):
    ans = 1
    while n:
        if n % 2:
            ans *= x
        x *= x
        n >>= 1
    return ans

"""
def nibu(x,n,r):
  ll = 0
  rr = r
  while True:
    mid = (ll+rr)//2

  if rr == mid:
    return ll
  if (ここに評価入れる):
    rr = mid
  else:
    ll = mid+1
"""

mod = 10**9+7 #出力の制限
N = 10**6 * 2 + 2
def cmb(n, r):
    if ( r<0 or r>n ):
        return 0
    r = min(r, n-r)
    return g1[n] * g2[r] * g2[n-r] % mod
def p(n,r):
    if ( r<0 or r>n ):
        return 0
    return g1[n] * g2[n-r] % mod

g1 = [1, 1] # 元テーブル
g2 = [1, 1] #逆元テーブル
inverse = [0, 1] #逆元テーブル計算用テーブル

for i in range( 2, N + 1 ):
    g1.append( ( g1[-1] * i ) % mod )
    inverse.append( ( -inverse[mod % i] * (mod//i) ) % mod )
    g2.append( (g2[-1] * inverse[-1]) % mod )
# a = cmb(n,r)

r1,c1,r2,c2= m()

p1 = 0

p2 = 0

p3 = 0

p4 = 0

for i in range(1,r2+2):
  p1 += cmb(c2+i,i)
  p1 %= mod
for i in range(1,r1+1):
  p2 += cmb(c2+i,i)
  p2 %= mod
for i in range(1,r2+2):
  p3 += cmb(c1+i-1,i)
  p3 %= mod
for i in range(1,r1+1):
  p4 += cmb(c1+i-1,i)
  p4 %= mod

print((p1-p2-p3+p4)%mod)

Submission status: Accepted

Solution code:
# coding: utf-8
import sys
import numpy as np

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

MOD = 10 ** 9 + 7

def cmb(n, k):
    if k < 0 or k > n: return 0 
    return fact[n] * fact_inv[k] % MOD * fact_inv[n-k] % MOD

def cumprod(arr, MOD):
    L = len(arr); Lsq = int(L**.5+1)
    arr = np.resize(arr, Lsq**2).reshape(Lsq, Lsq)
    for n in range(1, Lsq):
        arr[:, n] *= arr[:, n-1]; arr[:, n] %= MOD
    for n in range(1, Lsq):
        arr[n] *= arr[n-1, -1]; arr[n] %= MOD
    return arr.ravel()[:L]

def make_fact(U, MOD):
    x = np.arange(U, dtype=np.int64); x[0] = 1
    fact = cumprod(x, MOD)
    x = np.arange(U, 0, -1, dtype=np.int64); x[0] = pow(int(fact[-1]), MOD-2, MOD)
    fact_inv = cumprod(x, MOD)[::-1]
    return fact, fact_inv

U = 2 * 10 ** 6 + 3  # 階乗テーブルの上限
fact, fact_inv = make_fact(U, MOD)

r1, c1, r2, c2 = lr()
answer = cmb(r2+c2+2, r2+1) - 1
answer -= cmb(r2+c1+1, r2+1) - 1
answer -= cmb(r1+c2+1, c2+1) - 1
answer += cmb(r1+c1, r1) - 1
print(answer % MOD)
# 26

Submission status: Accepted

Solution code:
# coding: utf-8
import sys
import numpy as np

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

MOD = 10 ** 9 + 7

def cmb(n, k):
    if k < 0 or k > n: return 0 
    return fact[n] * fact_inv[k] % MOD * fact_inv[n-k] % MOD

def cumprod(arr, MOD):
    L = len(arr); Lsq = int(L**.5+1)
    arr = np.resize(arr, Lsq**2).reshape(Lsq, Lsq)
    for n in range(1, Lsq):
        arr[:, n] *= arr[:, n-1]; arr[:, n] %= MOD
    for n in range(1, Lsq):
        arr[n] *= arr[n-1, -1]; arr[n] %= MOD
    return arr.ravel()[:L]

def make_fact(U, MOD):
    x = np.arange(U, dtype=np.int64); x[0] = 1
    fact = cumprod(x, MOD)
    x = np.arange(U, 0, -1, dtype=np.int64); x[0] = pow(int(fact[-1]), MOD-2, MOD)
    fact_inv = cumprod(x, MOD)[::-1]
    return fact, fact_inv

U = 2 * 10 ** 6 + 10  # 階乗テーブルの上限
fact, fact_inv = make_fact(U, MOD)

r1, c1, r2, c2 = lr()
answer = cmb(r2+c2+2, r2+1) - 1
answer -= cmb(r2+c1+1, r2+1) - 1
answer -= cmb(r1+c2+1, c2+1) - 1
answer += cmb(r1+c1, r1) - 1
print(answer % MOD)
# 26

Submission status: Accepted

Solution code:

##mod,nについての制約は自分でいかに記入する
mod=10**9+7
def find_power(n,mod):
    # 0!からn!までのびっくりを出してくれる関数(ただし、modで割った値に対してである）
    powlist=[0]*(n+1)
    powlist[0]=1
    powlist[1]=1
    for i in range(2,n+1):
        powlist[i]=powlist[i-1]*i%(mod)
    return powlist
 #あるかずxのn乗をmodで割ったあまりを返す関数pow_cal(x,n,mod)
def pow_cal(x,n,mod):
    if n==0:
        return 1
    elif n==1:
        return x%mod
    elif n>=2:
        if n%2==0:
            return (pow_cal(x,n//2,mod)**2)%mod
        else:
            return (x*pow_cal(x,n//2,mod)**2)%mod

def find_inv_power(n,mod):
    #0!からn!までの逆元を素数modで割ったあまりリストを作る関数
    c=1
    uselist=[0 for i in range(n+1)]
    for i in range(1,n+1):
        c*=i
        c%=mod
    first=pow_cal(c,mod-2,mod)
    uselist[n]=first
    for i in range(n,0,-1):
        uselist[i-1]=(uselist[i]*i)%(mod)
    return uselist
    
A=find_power(2*10**6+10,mod)
B=find_inv_power(2*10**6+10,mod)

def combi(n,r,mod):
    if n<r:
        return 0
    elif n>=r:
        return (A[n]*B[r]*B[n-r])%(mod)
    
r1,c1,r2,c2=map(int,input().split())

mod=10**9+7     

K=combi(r2+c2+2,c2+1,mod)-combi(r2+c1+1,c1,mod)-combi(r1+c2+1,r1,mod)+combi(r1+c1,c1,mod)

print(K%mod)

Submission status: Accepted

Solution code:
import sys
import math
import numpy
input = sys.stdin.buffer.readline
 
def main():
    a,b,c,d = map(int,input().split())
    MOD = 10**9+7
    N = c+d+5
    fac = [0 for _ in range(N+1)]
    fac[0],fac[1] = 1,1
 
    for i in range(2,N+1):
        fac[i] = (fac[i-1]*i)%MOD
       
    def comb(x,y):
        return (fac[x+y]*pow(fac[x],MOD-2,MOD)*pow(fac[y],MOD-2,MOD))%MOD
 
    print((comb(c+1,d+1)-comb(c+1,b)-comb(d+1,a)+comb(a,b))%MOD)
   
if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
import sys
import math
input = sys.stdin.buffer.readline
 
def main():
    a,b,c,d = map(int,input().split())
    MOD = 10**9+7
    N = c+d+5
    fac = [0 for _ in range(N+1)]
    fac[0],fac[1] = 1,1
 
    for i in range(2,N+1):
        fac[i] = (fac[i-1]*i)%MOD
        
    def comb(x,y):
        return (fac[x+y]*pow(fac[x],MOD-2,MOD)*pow(fac[y],MOD-2,MOD))%MOD
 
    print((comb(c+1,d+1)-comb(c+1,b)-comb(d+1,a)+comb(a,b))%MOD)
    
if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.buffer.readline
 
def main():
    a,b,p,d = map(int,input().split())
    MOD = 10**9+7
    N = p+d+5
    fac = [0 for _ in range(N+1)]
    fac[0],fac[1] = 1,1
 
    for i in range(2,N+1):
        fac[i] = (fac[i-1]*i)%MOD
        
    def comb(x,y):
        return (fac[x+y]*pow(fac[x],MOD-2,MOD)*pow(fac[y],MOD-2,MOD))%MOD
 
    print((comb(p+1,d+1)-comb(p+1,b)-comb(d+1,a)+comb(a,b))%MOD)
    
if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.buffer.readline
 
def main():
    a,b,c,d = map(int,input().split())
    MOD = 10**9+7
    N = c+d+5
    fac = [0 for _ in range(N+1)]
    fac[0],fac[1] = 1,1
 
    for i in range(2,N+1):
        fac[i] = (fac[i-1]*i)%MOD
        
    def comb(g,h):
        return (fac[g+h]*pow(fac[g],MOD-2,MOD)*pow(fac[h],MOD-2,MOD))%MOD
 
    print((comb(c+1,d+1)-comb(c+1,b)-comb(d+1,a)+comb(a,b))%MOD)
    
if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(500*500)
def modpow(a,n,p):
    if n==0:
        return 1
    x=modpow(a,n//2,p)
    x=(x*x)%p
    if (n%2)==1:
        x=(x*a)%p
    return x%p
def modinv(a,p):
    return modpow(a,p-2,p)

r1,c1,r2,c2=map(int,input().split())
n1=r2+c2+2
n2=r2+c1+1
n3=r1+c2+1
n4=r1+c1
l=[r2+1,r2+1,r1,r1]
p=10**9+7
buf=1
cnt=0
l=[0]*(10**7+10)
inv=[0]*(10**7+10)
l[1]=1
for i in range(2,n1+3,1):#n1+1
    l[i]=(l[i-1]*i)%p
print((((l[n1]*modinv(l[r2+1],p)*modinv(l[n1-r2-1],p))%p)-(l[n2]*modinv(l[r2+1],p)*modinv(l[n2-r2-1],p))-(l[n3]*modinv(l[r1],p)*modinv(l[n3-r1],p))+(l[n4]*modinv(l[r1],p)*modinv(l[n4-r1],p)))%p)

Submission status: Accepted

Solution code:
def main():
    mod = 10**9+7
    fact = [1, 1]
    for i in range(2, 2*(10**6)+10):
        fact.append(fact[-1]*i % mod)

    r1, c1, r2, c2 = map(int, input().split())
    r1 -= 1
    c1 -= 1

    def calc(r, c):
        return (pow(fact[c+1]*fact[r+1] % mod, mod-2, mod)*fact[r+c+2]-1) % mod

    print((calc(r2, c2)-calc(r1, c2)-calc(r2, c1)+calc(r1, c1)) % mod)


main()

Submission status: Accepted

Solution code:
nmax = (10**6+1)*2
mod = 10**9+7

fac = [1]*nmax
finv = [1]*nmax
inv = [1]*nmax
def ncr_pre():
    for i in range(2,nmax):
        fac[i] = fac[i-1]*i % mod
        inv[i] = mod - inv[mod%i] * (mod//i) %mod
        finv[i] = finv[i-1] * inv[i] %mod

def ncr(n,r):
    if n<r:
        return 0
    if n<0 or r<0:
        return 0
    return fac[n]* (finv[r] * finv[n-r] %mod) %mod

def g(r,c):## r以下かつc以下の経路f(i,j)の総和
    ans = 0
    for i in range(1,r+2):
        ## f(i+1,c) =  f(i,0) + f(i,1) + ...f(i,c)
        ans += ncr(i+c,c)
        ans %=mod
    return ans

ncr_pre()
r1,c1,r2,c2 = map(int,input().split())
ans = g(r2,c2) - g(r1-1,c2) - g(r2,c1-1) + g(r1-1,c1-1)
print(ans % mod)

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.buffer.readline

def main():
    a,b,c,d = map(int,input().split())
    MOD = 10**9+7
    N = c+d+5
    fac = [0 for _ in range(N+1)]
    fac[0],fac[1] = 1,1

    for i in range(2,N+1):
        fac[i] = (fac[i-1]*i)%MOD
        
    def comb(x,y):
        return (fac[x+y]*pow(fac[x],MOD-2,MOD)*pow(fac[y],MOD-2,MOD))%MOD

    print((comb(c+1,d+1)-comb(c+1,b)-comb(d+1,a)+comb(a,b))%MOD)
    
if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
r1, c1, r2, c2 = map(int, input().split())
MOD = 10**9+7

def init_mod_c(lim=10**7, mod=10**9+7):
    fact = [1, 1] + [0] * (lim-1)
    fact_inv = [1, 1] + [0] * (lim-1)
    inv = [0, 1] + [0] * (lim-1)
    
    for i in range(2, lim+1):
        fact[i] = fact[i - 1] * i % mod
        inv[i] = mod - inv[mod % i] * (mod//i) % mod
        fact_inv[i] = fact_inv[i - 1] * inv[i] % mod

    def mod_c(n, m):
        if n < m or n < 0 or m < 0: return 0
        return fact[n] * (fact_inv[m] * fact_inv[n-m] % mod) % mod

    return mod_c

comb = init_mod_c()
pc = lambda r, c: comb(r+c, min(r, c))

ans = 0
for i in range(r1, r2+1):
    ans += pc(i+1, c2)
    if c1 > 0: ans -= pc(i+1, c1-1)
    ans %= MOD

print(ans)

Submission status: Accepted

Solution code:
r1,c1,r2,c2=map(int,input().split())
r2+=1
c2+=1
N=2*(10**6)+2
mod=10**9+7
fac=[1]*(N+2)
inv=[1]*(N+2)
t=1
for i in range(1,N+2):
    t*=i
    t%=mod
    fac[i]=t
t=pow(fac[N+1],mod-2,mod)
for i in range(N+1,0,-1):
    inv[i]=t
    t*=i
    t%=mod
def comb(n,r):
    return fac[n]*inv[n-r]*inv[r]%mod
print((comb(r2+c2,c2)-comb(r2+c1,c1)-comb(r1+c2,c2)+comb(r1+c1,c1))%mod)

Submission status: Accepted

Solution code:
u, l, d, r = map(int, input().split())
mod = 10 ** 9 + 7

def extGCD(a, b):
    if b == 0:
        return a, 1, 0
    g, y, x = extGCD(b, a%b)
    y -= a//b * x
    return g, x, y

def moddiv(a, b):
    _, inv, _ = extGCD(b, mod)
    return (a * inv) % mod

f = [0] * (2 * 10 ** 6 + 10)
f[0] = 1
for i in range(1, 2 * 10 ** 6 + 10):
    f[i] = (f[i-1] * i) % mod

def comb(a, b):
    return moddiv(moddiv(f[a+b], f[a]), f[b])

ans = 0
d += 1
r += 1
ans += comb(d, r)
ans += comb(u, l)
ans -= comb(d, l)
ans -= comb(u, r)
print(ans % mod)

Submission status: Accepted

Solution code:

p = 10**9+7
kai_ = [1]
for i in range(1, 10 ** 7):
    kai_.append(kai_[-1] * i % p)


def kai(x):
    return kai_[x]


def comb(a, b):
    if a < 0 or b < 0:
        return 0
    elif a < b:
        return 0
    c = 1
    c *= kai(a)
    c *= pow(kai(b), p - 2, p)
    c *= pow(kai(a - b), p - 2, p)
    return c % p


r1, c1, r2, c2 = [int(i) for i in input().split()]


def s(r, c):
    return comb(r+c+2,r+1)


print((s(r2, c2) - s(r2, c1 - 1) - s(r1 - 1, c2) + s(r1 - 1, c1 - 1)) % p)

Submission status: Accepted

Solution code:
import sys
readline = sys.stdin.buffer.readline
r1,c1,r2,c2 = map(int,readline().split())
mod = 10**9+7
def pow(n,p,mod=10**9+7): #繰り返し二乗法(nのp乗)
    res = 1
    while p > 0:
        if p % 2 == 0:
            n = n ** 2 % mod
            p //= 2
        else:
            res = res * n % mod
            p -= 1
    return res % mod
def factrial_memo(n=3*10**6+1,mod=10**9+7):
    fact = [1, 1]
    for i in range(2, n + 1):
        fact.append((fact[-1] * i) % mod)
    return fact
def fermat_cmb(n, r, mod=10**9+7): #needs pow,factrial_memo(only fact). return nCk
    return fact[n] * pow(fact[r],mod-2) * pow(fact[n-r],mod-2) %mod
fact = factrial_memo()
r1,c1,r2,c2 = r1+1,c1+1,r2+1,c2+1
al = fermat_cmb(r2+c2,r2)
sub_r = fermat_cmb(r1-1+c2,r1-1)
sub_c = fermat_cmb(r2+c1-1,c1-1)
add_rc = fermat_cmb(r1-1+c1-1,r1-1)

al -= sub_r+sub_c
al += add_rc

print(al%mod)

Submission status: Accepted

Solution code:
r,c,R,C=map(int,input().split())
m=10**9+7
max_n=2*10**6+1
fac=[1]*(max_n+1)
inv=[1]*(max_n+1)
ifac=[1]*(max_n+1)
for n in range(2,max_n+1):
    fac[n]=(fac[n-1]*n)%m
    inv[n]=m-inv[m%n]*(m//n)%m
    ifac[n]=(ifac[n-1]*inv[n])%m
def comb(n,k):
    if n<k or n<0 or k<0:
        return 0
    return (fac[n]*ifac[k]*ifac[n-k])%m
def f(r,c):
    return sum([comb(i+1+c,c) for i in range(r+1)])%m
print((f(R,C)-f(R,c-1)-f(r-1,C)+f(r-1,c-1))%m)

Submission status: Accepted

Solution code:
import sys
import time
# input = sys.stdin.buffer.readline
def getN():
    return int(input())
def getNM():
    return map(int, input().split())
def getlist():
    return list(map(int, input().split()))
import math
import heapq
import bisect
from collections import defaultdict, Counter, deque
MOD = 10**9 + 7
INF = 10**21

def routes_from_zero(r,c, factorial, gyaku):
    ret = 0
    for i in range(r + 1):
        tmp = 1
        tmp *= factorial[i+c+1]
        # tmp %= MOD
        tmp *= gyaku[c]
        # tmp %= MOD
        tmp *= gyaku[i+1]
        # tmp %= MOD

        ret += tmp
        ret %= MOD

    return ret

def main():
    r1, c1, r2, c2 = getlist()
    # factorial = [1]
    # tmp = 1
    # t1 = time.time()
    # for i in range(1, r2 + c2 + 5):
    #     tmp *= i
    #     tmp %= MOD
    #     factorial.append(tmp)
    # print(time.time() - t1)
    # gyaku = [pow(i, MOD - 2, MOD) for i in factorial]
    # print(time.time() - t1)
    SIZE = 2 * 10 ** 6 + 10 ** 5
    SIZE += 1
    inv = [0] * SIZE  # inv[j] = j^{-1} mod MOD
    fac = [0] * SIZE  # fac[j] = j! mod MOD
    finv = [0] * SIZE  # finv[j] = (j!)^{-1} mod MOD
    inv[1] = 1
    fac[0] = fac[1] = 1
    finv[0] = finv[1] = 1
    for i in range(2, SIZE):
        inv[i] = MOD - (MOD // i) * inv[MOD % i] % MOD
        fac[i] = fac[i - 1] * i % MOD
        finv[i] = finv[i - 1] * inv[i] % MOD
    factorial = fac
    gyaku = finv
    # print(time.time() - t1)
    # return
    # gyaku = [1 for i in range(2000000)]
    # print(routes_from_zero(r2, c2))
    # print(routes_from_zero(r1, c2))
    # print(routes_from_zero(r2, c1))
    # print(routes_from_zero(r1, c1))
    ans = routes_from_zero(r2, c2, factorial, gyaku) - routes_from_zero(r1 - 1, c2, factorial, gyaku)\
          - routes_from_zero(r2, c1 - 1, factorial, gyaku) + routes_from_zero(r1 - 1, c1 - 1, factorial, gyaku)
    print(ans % MOD)

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
r1, c1, r2, c2 = map(int, input().split())
L = 10 ** 9 + 7

# 互除法
def get_euclidian (A, B):
  if B == 1:
    return (1)
  else:
    return (int((1 - A * get_euclidian (B, A % B)) / B))

# 階乗計算
F = [1]
for i in range(1, r2 + c2 + 3):
  F.append((F[i - 1] * i) % L)

# 組み合わせ計算
def get_combi (n, r):

  Euc = get_euclidian(L, (F[r] * F[n - r]) % L)
  return ((F[n] * Euc) % L)

combi1 = get_combi(r2 + c2 + 2, r2 + 1)
combi2 = get_combi(r2 + c1 + 1, c1)
combi3 = get_combi(r1 + c2 + 1, r1)
combi4 = get_combi(r1 + c1, r1)

print ((int(combi1 - combi2 - combi3 + combi4) + L) % L)

Submission status: Accepted

Solution code:
mod = 10**9 + 7

r1, c1, r2, c2 = map(int, input().split())

def inv(x):
  m = mod
  u = 1
  v = 0
  while(m):
    t = x // m
    x -= t * m
    x, m = m, x
    u -= t * v
    u, v = v, u
  u %= mod
  if u < 0:
    u += mod
  return u

fac = [1]
for i in range(1, r2 + c2 + 3):
  fac.append(fac[i - 1] * i % mod)

def paths(r, c):
  return fac[r + c + 2] * inv(fac[r + 1] * fac[c + 1]) % mod

f = paths(r2, c2) - paths(r2, c1 - 1) - paths(r1 - 1, c2) + paths(r1 - 1, c1 - 1)
f %= mod
if f < 0:
   f += mod
print(f)

Submission status: Accepted

Solution code:
class Combination:
    """
    SIZEが10^6程度以下の二項係数を何回も呼び出したいときに使う
    使い方:
    comb = Combination(SIZE, MOD)
    comb(10, 3) => 120
    """

    def __init__(self, N, MOD=10 ** 9 + 7):
        self.MOD = MOD
        self.fact, self.inv = self._make_factorial_list(N)

    def __call__(self, n, k):
        if k < 0 or k > n:
            return 0
        res = self.fact[n] * self.inv[k] % self.MOD
        res = res * self.inv[n - k] % self.MOD
        return res

    def _make_factorial_list(self, N):
        fact = [1] * (N + 1)
        inv = [1] * (N + 1)
        MOD = self.MOD
        for i in range(1, N + 1):
            fact[i] = (fact[i - 1] * i) % MOD
        inv[N] = pow(fact[N], MOD - 2, MOD)
        for i in range(N, 0, -1):
            inv[i - 1] = (inv[i] * i) % MOD
        return fact, inv


if __name__ == "__main__":
    r1, c1, r2, c2 = map(int, input().split())
    mod = 10 ** 9 + 7
    comb = Combination(2 * 10 ** 6 + 10, mod)

    def f(r, c):
        return comb(r+c+2, r+1)

    CD = (f(r2, c2) - f(r2, c1-1) + mod) % mod
    C = (f(r1-1, c2) - f(r1-1, c1-1) + mod) % mod
    ans = (CD - C + mod) % mod
    print(ans)

Submission status: Accepted

Solution code:
def getComb(n, k, MOD):
    if n < k:
        return 0
    if n-k < k:
        k = n-k
    # n!/(n-k)!
    comb = 1
    for x in range(n-k+1, n+1):
        comb = (comb * x) % MOD
    # k!
    d = 1
    for x in range(1, k+1):
        d = (d * x) % MOD
    # n!/((n-k)!*k!)
    comb *= pow(d, MOD-2, MOD)
    return comb % MOD

r1,c1,r2,c2 = map(int,input().split())
MOD = 10**9 + 7
ans = 0

ans += getComb(r2+c2+2, r2+1, MOD)
ans -= getComb(r2+c1+1, r2+1, MOD)
ans -= getComb(r1+c2+1, r1, MOD)
ans += getComb(r1+c1, r1, MOD)

print(ans % MOD)

Submission status: Accepted

Solution code:
MAX = 2*10**6+100
fact = [0]*MAX
inv = [0]*MAX
finv = [0]*MAX
 
def C_init():
    fact[0] = 1
    fact[1] = 1
    finv[0] = 1
    finv[1] = 1
    inv[1] = 1
    
    for i in range(2, MAX):
        fact[i] = fact[i-1]*i%MOD
        inv[i] = MOD-inv[MOD%i]*(MOD//i)%MOD
        finv[i] = finv[i-1]*inv[i]%MOD
 
def C(n, r):
    if n<r:
        return 0
    if n<0 or r<0:
        return 0
    return fact[n]*(finv[r]*finv[n-r]%MOD)%MOD

def g(r, c):
    return ((r+2)*C(c+r+2, r+2)-c-1)*inv[c+1]

r1, c1, r2, c2 = map(int, input().split())
MOD = 10**9+7
C_init()
ans = g(r2, c2)-g(r2, c1-1)-g(r1-1, c2)+g(r1-1, c1-1)
ans %= MOD

print(ans)

Submission status: Accepted

Solution code:
def main():
    r1, c1, r2, c2 = (int(i) for i in input().split())
    m = r2 + c2 + 3
    fac = [0] * m
    finv = [0] * m
    inv = [0] * m
    MOD = 10**9 + 7

    def COMBinitialize(m):
        fac[0] = 1
        finv[0] = 1
        if m > 1:
            fac[1] = 1
            finv[1] = 1
            inv[1] = 1
            for i in range(2, m):
                fac[i] = fac[i-1] * i % MOD
                inv[i] = MOD - inv[MOD % i] * (MOD // i) % MOD
                finv[i] = finv[i - 1] * inv[i] % MOD

    def COMB(n, k):
        if n < k:
            return 0
        if n < 0 or k < 0:
            return 0
        return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD

    COMBinitialize(m)
    ans = COMB(r2+c2+2, r2+1)
    ans -= COMB(r1+c2+1, r1) + COMB(r2+c1+1, c1)
    ans %= MOD
    ans += COMB(r1+c1, r1)
    print(ans % MOD)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
#
# 　　  ⋀_⋀　 
#　　  (･ω･)  
# .／ Ｕ ∽ Ｕ＼
#  │＊　合　＊│
#  │＊　格　＊│ 
#  │＊　祈　＊│ 
#  │＊　願　＊│ 
#  │＊　　　＊│ 
#      ￣
#
import sys
sys.setrecursionlimit(10**6)
input=sys.stdin.readline
from math import floor,sqrt,factorial,hypot,log #log2ないｙｐ
from heapq import heappop, heappush, heappushpop
from collections import Counter,defaultdict,deque
from itertools import accumulate,permutations,combinations,product,combinations_with_replacement
from bisect import bisect_left,bisect_right
from copy import deepcopy
from fractions import gcd
from random import randint
def ceil(a,b): return (a+b-1)//b
inf=float('inf')
mod = 10**9+7
def pprint(*A): 
    for a in A:     print(*a,sep='\n')
def INT_(n): return int(n)-1
def MI(): return map(int,input().split())
def MF(): return map(float, input().split())
def MI_(): return map(INT_,input().split())
def LI(): return list(MI())
def LI_(): return [int(x) - 1 for x in input().split()]
def LF(): return list(MF())
def LIN(n:int): return [I() for _ in range(n)]
def LLIN(n: int): return [LI() for _ in range(n)]
def LLIN_(n: int): return [LI_() for _ in range(n)]
def LLI(): return [list(map(int, l.split() )) for l in input()]
def I(): return int(input())
def F(): return float(input())
def ST(): return input().replace('\n', '')
#mint
class ModInt:
    def __init__(self, x):
        self.x = x % mod
    
    def __str__(self):
        return str(self.x)
    
    __repr__ = __str__

    def __add__(self, other):
        if isinstance(other, ModInt):
            return ModInt(self.x + other.x)
        else:
            return ModInt(self.x + other)

    __radd__ = __add__
        
    def __sub__(self, other):
        if isinstance(other, ModInt):
            return ModInt(self.x - other.x)
        else:
            return ModInt(self.x - other)

    def __rsub__(self, other):
        if isinstance(other, ModInt):
            return ModInt(other.x - self.x)
        else:
            return ModInt(other - self.x)

    def __mul__(self, other):
        if isinstance(other, ModInt):
            return ModInt(self.x * other.x)
        else:
            return ModInt(self.x * other)

    __rmul__ = __mul__

    def __truediv__(self, other):
        if isinstance(other, ModInt):
            return ModInt(self.x * pow(other.x, mod-2,mod))
        else:
            return ModInt(self.x * pow(other, mod - 2, mod))
            
    def __rtruediv(self, other):
        if isinstance(other, self):
            return ModInt(other * pow(self.x, mod - 2, mod))
        else:
            return ModInt(other.x * pow(self.x, mod - 2, mod))
            

    def __pow__(self, other):
        if isinstance(other, ModInt):
            return ModInt(pow(self.x, other.x, mod))
        else:
            return ModInt(pow(self.x, other, mod))
            

    def __rpow__(self, other):
        if isinstance(other, ModInt):
            return ModInt(pow(other.x, self.x, mod))
        else:
            return ModInt(pow(other, self.x, mod))

class BigCombination(object):

    def __init__(self, mod: int=10**9+7, max_n: int=3*(10**6)):
        fac, inv=[1], []
        fac_append, inv_append=fac.append, inv.append

        for i in range(1, max_n+1):
            fac_append(fac[-1] * i % mod)

        inv_append(pow(fac[-1], mod-2, mod))

        for i in range(max_n, 0, -1):
            inv_append(inv[-1] * i % mod)

        self.mod, self.factorial, self.inverse=mod, fac, inv[::-1]

    def get_combination(self, n, r):
        if n < r:
            return 0
        return self.factorial[n] * self.inverse[r] * self.inverse[n-r] % self.mod

    def get_permutation(self, n, r):
        if n < r:
            return 0
        return self.factorial[n] * self.inverse[n-r] % self.mod

def main():
    R1,C1,R2,C2 = MI()
    ans = ModInt(0)
    B = BigCombination()
    for r in range(R1,R2+1):
        ans += B.get_combination(C2+r+1,C2) - B.get_combination(C1-1+r+1,C1-1)
    print(ans)

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
r1,c1,r2,c2 = map(int,input().split())

MOD = 10**9+7
MAXN = r2+c2+5
fac = [1,1] + [0]*MAXN
for i in range(2,MAXN+2):
    fac[i] = fac[i-1] * i % MOD

def inv(n):
    return pow(n,MOD-2,MOD)

def comb(n,r):
    if n < r: return 0
    if n < 0 or r < 0: return 0
    return fac[n] * inv(fac[r]) * inv(fac[n-r]) % MOD

r2,c2 = r2+1,c2+1
ans = comb(r2+c2,r2) - comb(r2+c1,r2) - comb(r1+c2,r1) + comb(r1+c1,r1)
ans %= MOD
print(ans)

Submission status: Accepted

Solution code:
r1,c1,r2,c2=map(int,input().split())
mod=10**9+7
n=[1]*(r2+c2+3)
for i in range(r2+c2+2):
  n[i+1]=(n[i]*(i+1))%mod
def g(a,b):
  x,y,z=n[a+b],n[a],n[b]
  return (((x*pow(y,mod-2,mod))%mod)*pow(z,mod-2,mod))%mod
print((g(r2+1,c2+1)-g(r2+1,c1)-g(r1,c2+1)+g(r1,c1))%mod)

Submission status: Accepted

Solution code:
def paths(r,c):
  return facts[r+c]*ifacts[r]*ifacts[c]

mod=10**9+7
r1,c1,r2,c2=map(int,input().split())
facts=[1]*(r2+c2+10)
ifacts=[1]*(r2+c2+10)
for i in range(1,r2+c2+10):
  facts[i]=(facts[i-1]*i)%mod
  ifacts[i]=pow(facts[i],mod-2,mod)
ans=0
for i in range(r1+1,r2+2):
  ans+=paths(i,c2)-paths(i,c1-1)
  ans%=mod
print(ans)

Submission status: Accepted

Solution code:
p = 10 ** 9 + 7 # mod
N = (10 ** 6) * 2 + 10  # N は必要分だけ用意する
fact = [1, 1]
factinv = [1, 1]
inv = [0, 1]

for i in range(2, N + 1):
    fact.append((fact[-1] * i) % p)
    inv.append((-inv[p % i] * (p // i)) % p)
    factinv.append((factinv[-1] * inv[-1]) % p)

def cmb(r, n, p):
    if (r < 0) or (n < r):
        return 0
    r = min(r, n - r)
    return fact[n] * factinv[r] * factinv[n-r] % p

a = list(map(int,input().split()))
ans = cmb(a[2]+1,a[2]+a[3]+2,p) - cmb(a[1],a[2]+a[1]+1,p) - cmb(a[0],a[3]+a[0]+1,p) + cmb(a[0],a[0]+a[1],p)
print(ans%p)

Submission status: Accepted

Solution code:
k = 72
K = 1<<k
nu = lambda L: int("".join([bin(K+a)[-k:] for a in L[::-1]]), 2)
st = lambda n: bin(n)[2:] + "0"
li = lambda s, l: [int(a, 2) if len(a) else 0 for a in [s[-(i+1)*k-1:-i*k-1] for i in range(l)]]

def grow(d, v, h):
    h += [0] * d
    f = [(-1 if (i+d) % 2 else 1) * fainv[i] * fainv[d-i] % P * h[i] % P for i in range(d+1)]
    
    for idx, a in enumerate([d+1, d * fa[v-1] * fainv[v] % P, (d * fa[v-1] * fainv[v] + d + 1) % P]):
        t = [1] * (2*d+2)
        for i in range(1, 2*d+2): t[i] = t[i-1] * (a - d + i - 1) % P
        ti = [1] * (2*d+2)
        ti[-1] = pow(t[-1], P-2, P)
        for i in range(1, 2*d+2)[::-1]: ti[i-1] = ti[i] * (a - d + i - 1) % P
        
        g = [ti[i+1] * t[i] % P for i in range(2*d+1)]
        fg = li(st(nu(f) * nu(g)), d * 2 + 2)
            
        if idx == 1:
            for i in range(d+1):
                h[i] = h[i] * (fg[d+i] * t[d+i+1] % P * ti[i] % P) % P
        elif idx == 0:
            for i in range(d):
                h[i+d+1] = fg[d+i] * t[d+i+1] % P * ti[i] % P
        elif idx == 2:
            for i in range(d):
                h[i+d+1] = h[i+d+1] * (fg[d+i] * t[d+i+1] % P * ti[i] % P) % P
    return h

# Create a table of the factorial of the first v+2 multiples of v, i.e., [0!, v!, 2v!, ..., (v(v+1))!]
def create_table(v):
    s = 1
    X = [1, v+1]
    while s < v:
        X = grow(s, v, X)
        s *= 2
    table = [1]
    for x in X:
        table.append(table[-1] * x % P)
    return table

def fact(i, table):
    a = table[i//v]
    for j in range(i//v*v+1, i+1):
        a = a * j % P
    return a

P = 10**9+7
v = 1 << 11
fa = [1] * (2*v+2)
fainv = [1] * (2*v+2)
for i in range(2*v+1):
    fa[i+1] = fa[i] * (i+1) % P
fainv[-1] = pow(fa[-1], P-2, P)
for i in range(2*v+1)[::-1]:
    fainv[i] = fainv[i+1] * (i+1) % P

T = create_table(v)

f = lambda a, b: fact(a+b+2, T) * pow(fact(a+1, T) * fact(b+1, T), P-2, P) % P
r1, c1, r2, c2 = map(int, input().split())
print((f(r2, c2) - f(r2, c1-1) - f(r1-1, c2) + f(r1-1, c1-1)) % P)

Submission status: Accepted

Solution code:
nn = 2002002
P = 10**9+7
fa = [1] + [0] * nn
for i in range(nn): fa[i+1] = fa[i] * (i+1) % P
f = lambda a, b: fa[a+b+2] * pow(fa[a+1] * fa[b+1], P-2, P) % P - 1
r1, c1, r2, c2 = map(int, input().split())
print((f(r2, c2) - f(r2, c1-1) - f(r1-1, c2) + f(r1-1, c1-1)) % P)

Submission status: Accepted

Solution code:
k = 72
K = 1<<k
nu = lambda L: int("".join([bin(K+a)[-k:] for a in L[::-1]]), 2)
st = lambda n: bin(n)[2:] + "0"
li = lambda s, l: [int(a, 2) if len(a) else 0 for a in [s[-(i+1)*k-1:-i*k-1] for i in range(l)]]

def grow(d, v, h):
    h += [0] * d
    f = [(-1 if (i+d) % 2 else 1) * fainv[i] * fainv[d-i] % P * h[i] % P for i in range(d+1)]
    
    for idx, a in enumerate([d+1, d * fa[v-1] * fainv[v] % P, (d * fa[v-1] * fainv[v] + d + 1) % P]):
        g = [pow(a - d + i - 1, P-2, P) if i else 0 for i in range(2*d+2)]
        fg = li(st(nu(f) * nu(g)), d * 8 - 1)
        p = 1
        for i in range(d+1):
            p = p * (a-i) % P
        for i in range(d+1):
            fg[d+i+1] = fg[d+i+1] * p % P
            p = p * (a+i+1) % P * pow(a-d+i, P-2, P) % P
        if idx == 1:
            for i in range(d+1):
                h[i] = h[i] * fg[d+i+1] % P
        elif idx == 0:
            for i in range(d):
                h[i+d+1] = fg[d+i+1]
        elif idx == 2:
            for i in range(d):
                h[i+d+1] = h[i+d+1] * fg[d+i+1] % P
    return h

# Create a table of the factorial of the first v+2 multiples of v, i.e., [0!, v!, 2v!, ..., (v(v+1))!]
def create_table(v):
    s = 1
    X = [1, v+1]
    while s < v:
        X = grow(s, v, X)
        s *= 2
    table = [1]
    for x in X:
        table.append(table[-1] * x % P)
    return table

def fact(i, table):
    a = table[i//v]
    for j in range(i//v*v+1, i+1):
        a = a * j % P
    return a

P = 10**9+7
v = 1 << 11
fa = [1] * (2*v+2)
fainv = [1] * (2*v+2)
for i in range(2*v+1):
    fa[i+1] = fa[i] * (i+1) % P
fainv[-1] = pow(fa[-1], P-2, P)
for i in range(2*v+1)[::-1]:
    fainv[i] = fainv[i+1] * (i+1) % P

T = create_table(v)

f = lambda a, b: fact(a+b+2, T) * pow(fact(a+1, T) * fact(b+1, T), P-2, P) % P
r1, c1, r2, c2 = map(int, input().split())
print((f(r2, c2) - f(r2, c1-1) - f(r1-1, c2) + f(r1-1, c1-1)) % P)