Problem:
Problem K:
ワープホール
20XX年、遠く離れた場所に対する効率的な物質転送方式が確立され、人類の宇宙への進出はますます加速されることになった。この転送方式は、より遠くに物質を転送しようとすると、原則的により大きな物質の転送が可能になる点で革新的であった。転送方式の詳細を次に記す。
まず転送対象となる物質は、スタート座標(1, 1)にて単位質量毎のパーティクルに分割される。各パーティクルには、各々異なる波動エネルギーが与えられなければならない。波動エネルギーは、
V
と
H
からなる任意の長さの文字列で表現され、パーティクルの宇宙空間における漂い方を規定する。
V
は座標上(+1, 0)の移動を意味し、
H
は(0, +1)の移動を意味する。例えば、
VHHV
という波動エネルギーが与えられたパーティクルは、(2, 1), (2, 2), (2, 3) という軌跡で宇宙を漂った後、座標(3, 3)に辿り着く。
また、宇宙空間には複数のワープホールが存在し、パーティクルの軌跡に影響を与える。ワープホールには入口と出口があり、パーティクルがワープホールの入口に移動した場合、必ず出口の座標にワープすることになる。i番目のワープホールの入口と出口の座標を(a
i
, b
i
), (c
i
, d
i
)とすると、a
i
≤ c
i
, b
i
≤ d
i
, (a
i
, b
i
) ≠ (c
i
, d
i
)の条件が満たされており、ワープホールの入口は、他のワープホールの入口と同じ座標や、(1, 1)には存在しないことが保証されている。ただし、複数の出口が同じ場所にあったり、あるワープホールの出口に別のワープホールの入口がある場合はある(この場合は連続でワープする)。
例えば、(1, 2)を入口とし、(3, 2)を出口とするワープホールが存在した場合、
HH
と波動エネルギーを与えられたパーティクルは、(1, 2)へ移動後、(3, 2)へワープし、 (3, 3)へと辿り着く。
パーティクルは波動エネルギーを与えられると一瞬でそれに従って移動する。全てのパーティクルが同時に目的地点へ辿り着くと、自動的に元の物質へと再構成される。
あなたは宇宙開発機構のプログラマである。転送の目的座標 (N, M) と K 個のワープホールの座標対が与えられるので、一度に転送可能な物質の最大質量を求めるプログラムを書いてほしい。答えは非常に大きい数になる可能性があるため、1,000,000,007で割った余りを出力せよ。
Input
N M K
a
1
b
1
c
1
d
1
...
a
K
b
K
c
K
d
K
1 ≤ N,M ≤ 10
5
, 0 ≤ K ≤ 10
3
を満たす。また、
任意の 1 ≤ i ≤ K に対して a
i
≤ c
i
, b
i
≤ d
i
, (a
i
, b
i
) ≠ (c
i
, d
i
) を満たす。
Output
最大質量を 1,000,000,007 で割ったあまりを1行で出力せよ。
Notes on Test Cases
上記入力形式で複数のデータセットが与えられます。各データセットに対して上記出力形式で出力を行うプログラムを作成して下さい。
N, M, K がすべて 0 のとき入力の終わりを示します。
Sample Input
4 4 1
2 2 3 3
1 4 1
1 2 1 3
5 5 2
2 2 3 4
3 3 5 3
5 5 3
4 4 5 5
2 2 3 3
3 3 4 4
100000 100000 1
2 2 99999 99999
1 1 0
0 0 0
Output for Sample Input
12
1
26
18
615667476
1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

#define rep(i, j, k) for (int i = j; i < k; ++i)
#define irep(i, j, k) for (int i = j - 1; i >= k; --i)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int > Pii;
typedef pair<Pii, Pii > Tii;

const double pi = acos(-1.0);
const int INF = INT_MAX;
const ll LLINF = LLONG_MAX;
const int MAX_N = 1e5 + 10;
const int MOD = 1e9 + 7;

inline int add(int a, int b) { return (a + b) % MOD;}
inline int mul(int a, int b) { return 1ll * a * b % MOD;}
inline int del(int a, int b) { return (a - b + MOD) % MOD;}

int N, M, K, dp[MAX_N], a, b, c, d;
int fact[2 * MAX_N];
vector<Tii> v;

void init_fact() {
	fact[0] = 1;
	rep(i, 1, 2 * MAX_N) fact[i] = mul(i, fact[i - 1]);
}
int inv(int x) {
	return x == 1? 1 : (MOD - mul((MOD / x), inv(MOD % x)) % MOD) % MOD;
}
int C(int n, int k) {
	return mul(mul(fact[n], inv(fact[k])), inv(fact[n - k]));
}
int cal(Pii p1, Pii p2) {
	if (p2.first < p1.first || p2.second < p1.second) return 0;
	return C(p2.first + p2.second - p1.first - p1.second, p2.first - p1.first);
}
void solve() {
	memset(dp, 0, sizeof dp);
	sort(v.begin(), v.end());
	v.push_back(Tii(Pii(N, M), Pii(N + 1, M + 1)));
	rep(i, 0, K + 1) {
		dp[i] = C(v[i].first.first + v[i].first.second, v[i].first.first);
		rep(j, 0, i) 
			dp[i] = add(dp[i], mul(dp[j], del(cal(v[j].second, v[i].first), cal(v[j].first, v[i].first))));
	}
	printf("%d\n", dp[K]);
}
int main(int argc, char const *argv[])
{
	init_fact();
	while (scanf("%d%d%d", &N, &M, &K), N + M + K) {
		--N, --M;
		v.clear();
		rep(i, 0, K) {
			scanf("%d%d%d%d", &a, &b, &c, &d);
			v.push_back(Tii(Pii(a - 1, b - 1), Pii(c - 1, d - 1)));
		}
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 610
memory_kb: 4576
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

const long long MOD = 1000000007;

long long modPow(long long base, long long exp, long long mod) {
    long long res = 1;
    while (exp > 0) {
        if (exp % 2 == 1) res = (res * base) % mod;
        base = (base * base) % mod;
        exp /= 2;
    }
    return res;
}

struct Factorial {
    vector<long long> fact;
    
    Factorial(int n) {
        fact.resize(n + 1);
        fact[0] = 1;
        for (int i = 1; i <= n; ++i) {
            fact[i] = (fact[i - 1] * i) % MOD;
        }
    }

    long long comb(int a, int b) {
        if (b > a || b < 0) return 0;
        long long num = fact[a];
        long long denom = (fact[b] * fact[a - b]) % MOD;
        return (num * modPow(denom, MOD - 2, MOD)) % MOD;
    }

    long long paths(int sx, int sy, int tx, int ty) {
        if (sx > tx || sy > ty) return 0;
        int totalMoves = (tx - sx) + (ty - sy);
        return comb(totalMoves, tx - sx);
    }
};

struct Warp {
    int x1, y1, x2, y2;
};

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n, m, k;
    Factorial fact(200000);

    while (cin >> m >> n >> k) {
        if (n == 0 && m == 0 && k == 0) break;

        vector<Warp> warps(k);
        for (int i = 0; i < k; ++i) {
            cin >> warps[i].x1 >> warps[i].y1 >> warps[i].x2 >> warps[i].y2;
            warps[i].x1--; warps[i].y1--;
            warps[i].x2--; warps[i].y2--;
        }

        warps.push_back({m - 1, n - 1, m - 1, n - 1});
        sort(warps.begin(), warps.end(), [](const Warp &a, const Warp &b) {
            if (a.x1 != b.x1) return a.x1 < b.x1;
            return a.y1 < b.y1;
        });

        vector<long long> dp(warps.size(), 0);
        for (int i = 0; i < warps.size(); ++i) {
            dp[i] = fact.paths(0, 0, warps[i].x1, warps[i].y1);
            for (int j = 0; j < i; ++j) {
                long long warpPaths = fact.paths(warps[j].x2, warps[j].y2, warps[i].x1, warps[i].y1);
                long long directPaths = fact.paths(warps[j].x1, warps[j].y1, warps[i].x1, warps[i].y1);
                dp[i] = (dp[i] + dp[j] * ((warpPaths - directPaths + MOD) % MOD)) % MOD;
            }
        }
        cout << dp.back() << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 4632
final_rank: 5

code_snippet: /*
对k个虫洞使用增量法，按起点坐标pair由大到小加入影响。
影响使用容斥计算即可。
代码中f[i] = 在目前的影响下(x[i], y[i])到终点的方案数。
*/ 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <utility>
#include <queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldouble;
const int LEN = 100000;

struct fastio {
  int it, len;
  char s[LEN + 5];
  fastio() {
    it = len = 0;
  }
  char get() {
    if (it < len) return s[it++];
    it = 0, len = fread(s, 1, LEN, stdin);
    return len ? s[it++] : EOF;
  }
  bool notend() {
    char c;
    for (c = get(); c == ' ' || c == '\n' || c == '\r'; c = get());
    if (it) it--;
    return c != EOF;
  }
  void put(char c) {
    if (it == LEN) fwrite(s,1,LEN,stdout), it = 0;
    s[it++] = c;
  }
  void flush() {
    fwrite(s, 1, it, stdout);
  }
}buff, bufo;
inline int getint() {
  char c; int res = 0, sig = 1;
  for (c = buff.get(); c < '0' || c > '9'; c = buff.get()) if(c == '-') sig = -1;
  for (; c >= '0' && c <= '9'; c = buff.get()) res = res * 10 + (c - '0');
  return sig * res;
}
inline ll getll() {
  char c; ll res = 0, sig = 1;
  for (c = buff.get(); c < '0' || c > '9'; c = buff.get()) if (c == '-') sig = -1;
  for (; c >= '0' && c <= '9'; c = buff.get()) res = res * 10 + (c - '0');
  return sig * res;
}
inline void putint(int x, char suf) {
  if (!x) bufo.put('0');
  else {
    if (x < 0) bufo.put('-'), x = -x;
    int k = 0; char s[15];
    while (x) {
      s[++k] = x % 10 + '0';
      x /= 10;
    }
    for (; k; k--) bufo.put(s[k]);
  }
  bufo.put(suf);
}
inline void putll(ll x, char suf) {
  if (!x) bufo.put('0');
  else {
    if (x < 0) bufo.put('-'), x = -x;
    int k = 0; char s[25];
    while (x) {
      s[++k] = x % 10 + '0';
      x /= 10;
    }
    for (; k; k--) bufo.put(s[k]);
  }
  bufo.put(suf);
}
inline char get_char() {
  char c;
  for (c = buff.get(); c == ' ' || c == '\n' || c == '\r'; c = buff.get());
  return c;
}

#define maxn 200005
#define maxk 1005
#define mp make_pair
const ll mod = 1000000007;

ll modpow(ll x, ll y) {
  ll res = 1;
  while (y) {
    if (y & 1) (res *= x) %= mod;
    y >>= 1;
    (x *= x) %= mod;
  }
  return res;
}
ll modInv(ll x) { return modpow(x, mod - 2); }

ll fct[maxn], invFct[maxn];
ll C(int x, int y) {
  return fct[x] * invFct[y] % mod * invFct[x - y] % mod;
}

int n, m, k, x[maxk << 1], y[maxk << 1];
ll f[maxk << 1];
struct Hole {
  int a, b, c, d;
  bool operator < (const Hole &h) const {
    return mp(a, b) > mp(h.a, h.b);
  }
}h[maxk];

void solve() {
  for (int i = 1; i <= k; i++) {
    h[i].a = getint(), h[i].b = getint(),
    h[i].c = getint(), h[i].d = getint();
  }
  sort(h + 1, h + k + 1);
  x[1] = y[1] = 1;
  x[2 * k + 2] = n, y[2 * k + 2] = m;
  for (int i = 1; i <= k; i++) {
    x[i * 2] = h[i].a, y[i * 2] = h[i].b;
    x[i * 2 + 1] = h[i].c, y[i * 2 + 1] = h[i].d;
  }
  int p = 2 * k + 2;
  for (int i = 1; i <= p; i++) f[i] = C(n - x[i] + m - y[i], n - x[i]);
  for (int i = 1; i <= k; i++) {
    ll coe = f[i * 2 + 1] - f[i * 2];
    for (int j = 1; j <= p; j++) {
      if (x[j] <= x[i * 2] && y[j] <= y[i * 2]) {
        (f[j] += C(x[i * 2] - x[j] + y[i * 2] - y[j], x[i * 2] - x[j]) * coe) %= mod;
      }
    }
  }
  putll((f[1] + mod) % mod, '\n');
}

int main() {
  fct[0] = 1;
  for (int i = 1; i <= 200000; i++) fct[i] = fct[i - 1] * i % mod;
  invFct[200000] = modInv(fct[200000]);
  for (int i = 200000; i >= 1; i--) invFct[i - 1] = invFct[i] * i % mod;
  while ((n = getint()) + (m = getint()) + (k = getint())) solve();
  bufo.flush();
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 6396
final_rank: 3

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005

struct Info{
	Info(ll arg_row1,ll arg_col1,ll arg_row2,ll arg_col2){
		row1 = arg_row1;
		col1 = arg_col1;
		row2 = arg_row2;
		col2 = arg_col2;
	}
	bool operator<(const struct Info &arg) const{

		if(row1 != arg.row1){

			return row1 < arg.row1;
		}else{

			return col1 < arg.col1;
		}
	}

	ll row1,col1,row2,col2;
};

ll H,W,K;
ll dp[1005];
ll fact[SIZE];


ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_pow(ll x,ll count, ll mod){

	if(count == 0)return 1;
	ll ret = mod_pow((x*x)%mod,count/2,mod);
	if(count%2 == 1){

		ret = (ret*x)%mod;
	}
	return ret;
}


ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}

ll mod_fact(ll n,ll p,ll &e){
	e = 0;
	if(n == 0)return 1;

	int res = mod_fact(n/p,p,e);
	e += n/p;

	if(n/p%2 != 0)return res*(p-fact[n%p])%p;
	return res*fact[n%p]%p;
}


ll nCm(ll n,ll m,ll p){
   if(n < m) return 0;
   ll e1,e2,e3;
   ll a1 = mod_fact(n,p,e1),a2 = mod_fact(m,p,e2),a3 = mod_fact(n-m,p,e3);
   if(e1 > e2+e3)return 0;
   return a1 * mod_inverse(a2*a3%p,p)%p;
}

void func(){

	vector<Info> V;

	ll col1,row1,col2,row2;

	for(int loop = 0; loop < K; loop++){

		scanf("%lld %lld %lld %lld",&col1,&row1,&col2,&row2);

		V.push_back(Info(row1,col1,row2,col2));
	}

	sort(V.begin(),V.end());

	ll minus,A,B;

	for(int i = 0; i < V.size(); i++){

		dp[i] = nCm(V[i].row1+V[i].col1-2,V[i].row1-1,MOD);

		for(int k = 0; k <= i-1; k++){
			if(V[k].col1 > V[i].col1)continue;

			A = nCm((V[i].row1-V[k].row1+V[i].col1-V[k].col1),V[i].row1-V[k].row1,MOD);
			if(V[k].col2 > V[i].col1 || V[k].row2 > V[i].row1){

				B = 0;

			}else{

				B = nCm((V[i].row1-V[k].row2+V[i].col1-V[k].col2),V[i].row1-V[k].row2,MOD);
			}

			minus = (A-B+MOD)%MOD;
			minus *= dp[k];
			minus %= MOD;

			dp[i] = (dp[i]-minus+MOD)%MOD;
		}
	}

	ll ans = nCm(H+W-2,H-1,MOD);

	for(int i = 0; i < V.size(); i++){

		A = nCm(H-V[i].row1+W-V[i].col1,H-V[i].row1,MOD);
		B = nCm(H-V[i].row2+W-V[i].col2,H-V[i].row2,MOD);

		minus = (A-B+MOD)%MOD;
		minus *= dp[i];
		minus %= MOD;

		ans = (ans-minus+MOD)%MOD;
	}

	printf("%lld\n",ans);
}


int main(){

	fact[0] = 1;
	for(ll i = 1; i < SIZE; i++){
		fact[i] = i*fact[i-1];
		fact[i] %= MOD;
	}

	while(true){

		scanf("%lld %lld %lld",&W,&H,&K);
		if(H == 0 && W == 0 && K == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 720
memory_kb: 4724
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i, l, r) for (int i = l; i <= r; i++)
#define dec(i, l, r) for (int i = l; i >= r; i--)
#define pii pair<int, int>
#define fi first
#define se second
#define pb push_back

const int maxn = 1e3 + 5;
const int maxnum = 2e5;
const int mod = 1e9 + 7;

int add(int a, int b) { return (a + b) % mod; }
int sub(int a, int b) { return (a - b + mod) % mod; }
int mul(int a, int b) { return 1LL * a * b % mod; }

struct worm {
    int x1, y1, x2, y2;
    bool operator<(const worm &o) const {
        if (x1 != o.x1) return x1 < o.x1;
        return y1 < o.y1;
    }
} w[maxn];

int dp[maxn], n, m, k;

inline ll ksm(ll _a, ll _n) {
    ll _r = 1;
    while (_n) {
        if (_n & 1) _r = _r * _a % mod;
        _a = _a * _a % mod;
        _n >>= 1;
    }
    return _r;
}

int fac[maxnum + 5];
int C(int _n, int _m) {
    return mul(mul(fac[_n], ksm(fac[_n - _m], mod - 2)), ksm(fac[_m], mod - 2));
}

int cal(int x1, int y1, int x2, int y2) {
    if (x1 > x2 || y1 > y2) return 0;
    return C(x2 - x1 + y2 - y1, x2 - x1);
}

int main() {
    fac[0] = 1;
    inc(i, 1, maxnum) fac[i] = mul(fac[i - 1], i);
    while (scanf("%d %d %d", &n, &m, &k) != EOF && n) {
        inc(i, 0, k - 1)
            scanf("%d %d %d %d", &w[i].x1, &w[i].y1, &w[i].x2, &w[i].y2);

        sort(w, w + k);
        w[k] = {n, m, n, m};
        for (int i = 0; i <= k; i++) {
            dp[i] = cal(1, 1, w[i].x1, w[i].y1);
            for (int j = 0; j < i; j++) {
                dp[i] = sub(
                    dp[i], mul(dp[j], cal(w[j].x1, w[j].y1, w[i].x1, w[i].y1)));
                dp[i] = add(
                    dp[i], mul(dp[j], cal(w[j].x2, w[j].y2, w[i].x1, w[i].y1)));
            }
        }
        printf("%d\n", dp[k]);
    }
}
accuracy: 1
time_ms: 490
memory_kb: 4036
final_rank: 9

code_snippet: #include <iostream>
#include <bits/stdc++.h>
 
using namespace std;
 
#define MOD 1000000007
 
inline int add(int a, int b)
{ return (a + b) % MOD; }
 
inline int sub(int a, int b)
{ return (a - b + MOD) % MOD; }
 
inline int mul(int a, int b)
{ return 1LL * a * b % MOD; }
 
// 虫洞
struct warp
{
    int x1, y1, x2, y2;
 
    bool operator<(const warp &w) const
    {
        if (x1 != w.x1)
            return x1 < w.x1;
        return y1 < w.y1;
    }
};
 
// return d = gcd(a, b) = ax + by
int extgcd(int a, int b, int &x, int &y)
{
    int g = a;
    x = 1;
    y = 0;
    if (b != 0)
        g = extgcd(b, a % b, y, x), y -= a / b * x;
    return g;
}
 
// 求a的逆元
int inv(int a)
{
    int x, y;
    extgcd(a, MOD, x, y);
    return (MOD + x % MOD) % MOD;
}
 
int fact[200010];   // 阶乘n!
void init_factorial()
{
    fact[0] = 1;
    for (int i = 0; i < 200000; ++i)
        fact[i + 1] = mul(fact[i], i + 1);
}
 
// 组合数（从n个序列空位中挑出k个）
inline int nck(int n, int k)
{ return mul(mul(fact[n], inv(fact[n - k])), inv(fact[k])); }
 
 
int N, M, K, dp[100010];
// dp[i] := 到第i个虫洞入口时的方案数
vector<warp> warps;
 
inline int calc(int x1, int y1, int x2, int y2) // 无虫洞模式下s到t的方案数
{
    if (x2 < x1 or y2 < y1)
        return 0;
    return nck(x2 - x1 + y2 - y1, x2 - x1);
}
 
int solve()
{
    memset(dp, 0, sizeof(dp));
    sort(begin(warps), end(warps));
    warps.push_back((warp) {N, M, N + 1, M + 1});
    for (int i = 0; i <= K; ++i)
    {
        dp[i] = nck(warps[i].x1 + warps[i].y1, warps[i].y1);
        for (int j = 0; j < i; ++j)
        {
            dp[i] = add(dp[i], mul(dp[j], sub(calc(warps[j].x2, warps[j].y2, warps[i].x1, warps[i].y1),    // j的终点到i的起点（紫色）
                                              calc(warps[j].x1, warps[j].y1, warps[i].x1, warps[i].y1)))); // j的起点到i的起点
        }
    }
    return dp[K];
}
 
bool input()
{
    warps.clear();
    scanf("%d%d%d", &N, &M, &K);
    --N;
    --M;
    int a, b, c, d;
    for (int i = 0; i < K; ++i)
    {
        scanf("%d%d%d%d", &a, &b, &c, &d);
        warps.push_back((warp) {a - 1, b - 1, c - 1, d - 1});
    }
    return N + 1 or M + 1 or K;
}
 
int main()
{
    init_factorial();
    while (input())
        cout << solve() << endl;
    return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 4316
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
inline int add(int a, int b) { return (a+b)%mod;}
inline int sub(int a, int b) { return (a-b+mod)%mod;}
inline int mul(int a, int b) { return 1LL*a*b%mod;}

struct warp
{
        int sx, sy, tx, ty;
        bool operator<(const warp &w) const {
                if(sx != w.sx) return sx < w.sx;
                return sy < w.sy;
        }
};

int extgcd(int a, int b, int &x, int &y)
{
        int g = a; x = 1; y = 0;
        if(b != 0) g = extgcd(b,a%b,y,x), y -= a/b*x;
        return g;
}
int inv(int a) {
        int x, y; extgcd(a,mod,x,y);
        return (mod+x%mod)%mod;
}
int fact[200010];
inline int nck(int n, int k) { return mul(mul(fact[n], inv(fact[n-k])), inv(fact[k]));}


int n, m, k, dp[100010];
// dp[i] := i番目のワープホールの入り口までの場合の数
vector<warp> warps;

inline int calc(int sx, int sy, int tx, int ty)
{
        if(tx < sx or ty < sy) return 0;
        return nck(tx-sx+ty-sy, tx-sx);
}

int solve()
{
        memset(dp,0,sizeof(dp));
        sort(begin(warps),end(warps));
        warps.push_back((warp){n,m, n+1, m+1});
        for (int i = 0; i <= k; i++) {
                dp[i] = nck(warps[i].sx+warps[i].sy, warps[i].sy);
                for (int j = 0; j < i; j++) {
                        dp[i] = add(dp[i], mul(dp[j], sub(calc(warps[j].tx, warps[j].ty, warps[i].sx,warps[i].sy),
                                                          calc(warps[j].sx, warps[j].sy, warps[i].sx,warps[i].sy))));
                }
        }
        return dp[k];
}

bool input()
{
        warps.clear();
        cin >> n >> m >> k;
        n--; m--;
        int a, b, c, d;
        for (int i = 0; i < k; i++) {
                cin >> a >> b >> c >> d;
                warps.push_back((warp){a-1,b-1,c-1,d-1});
        }
        return n+1 or m+1 or k;
}

int main()
{
        fact[0] = 1;
        for (int i = 0; i < 200000; i++) fact[i+1] = mul(fact[i], i+1);
        while(input()) cout << solve() << endl;
        return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 4256
final_rank: 6

code_snippet: #include <iostream>
#include <bits/stdc++.h>
 
using namespace std;
 
#define MOD 1000000007
 
inline int add(int a, int b)
{ return (a + b) % MOD; }
 
inline int sub(int a, int b)
{ return (a - b + MOD) % MOD; }
 
inline int mul(int a, int b)
{ return 1LL * a * b % MOD; }
 
// ????´?
struct warp
{
    int x1, y1, x2, y2;
 
    bool operator<(const warp &w) const
    {
        if (x1 != w.x1)
            return x1 < w.x1;
        return y1 < w.y1;
    }
};
 
// return d = gcd(a, b) = ax + by
int extgcd(int a, int b, int &x, int &y)
{
    int g = a;
    x = 1;
    y = 0;
    if (b != 0)
        g = extgcd(b, a % b, y, x), y -= a / b * x;
    return g;
}
 
// ?±?a?????????
int inv(int a)
{
    int x, y;
    extgcd(a, MOD, x, y);
    return (MOD + x % MOD) % MOD;
}
 
int fact[200010];   // ??¶???n!
void init_factorial()
{
    fact[0] = 1;
    for (int i = 0; i < 200000; ++i)
        fact[i + 1] = mul(fact[i], i + 1);
}
 
// ????????°??????n????????????????????????k??????
inline int nck(int n, int k)
{ return mul(mul(fact[n], inv(fact[n - k])), inv(fact[k])); }
 
 
int N, M, K, dp[100010];
// dp[i] := ??°?¬¬i???????´???\??£??¶???????????°
vector<warp> warps;
 
inline int calc(int x1, int y1, int x2, int y2) // ???????´??¨???????s??°t???????????°
{
    if (x2 < x1 or y2 < y1)
        return 0;
    return nck(x2 - x1 + y2 - y1, x2 - x1);
}
 
int solve()
{
    memset(dp, 0, sizeof(dp));
    sort(begin(warps), end(warps));
    warps.push_back((warp) {N, M, N + 1, M + 1});
    for (int i = 0; i <= K; ++i)
    {
        dp[i] = nck(warps[i].x1 + warps[i].y1, warps[i].y1);
        for (int j = 0; j < i; ++j)
        {
            dp[i] = add(dp[i], mul(dp[j], sub(calc(warps[j].x2, warps[j].y2, warps[i].x1, warps[i].y1),    // j???????????°i?????????????´???????
                                              calc(warps[j].x1, warps[j].y1, warps[i].x1, warps[i].y1)))); // j???????????°i?????????
        }
    }
    return dp[K];
}
 
bool input()
{
    warps.clear();
    scanf("%d%d%d", &N, &M, &K);
    --N;
    --M;
    int a, b, c, d;
    for (int i = 0; i < K; ++i)
    {
        scanf("%d%d%d%d", &a, &b, &c, &d);
        warps.push_back((warp) {a - 1, b - 1, c - 1, d - 1});
    }
    return N + 1 or M + 1 or K;
}
 
int main()
{
    init_factorial();
    while (input())
        cout << solve() << endl;
    return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 4440
final_rank: 8

code_snippet: /*
 * AOJ 2214: Warp Hall
 * ?¢??????????(1,1)?????°??????(m,n)???????¬??????????????????°?????????????????°????´???????????????´??\??°???????????????????´????????????????????°??§??????????
 * ?±????????????°DP
 * ???????????????????´?i(ai,bi)??°(ci,di)???(1,1)??°(ai,bi)???????????°???di??????????????\????´???????????????¢????????????????????????????????£???L??????????????????di????°?????´??????????DP?±???°?????°??????????´???\??£???????????°???
 */


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const LL MOD = 1000000007ll;

inline LL add(LL a, LL b) { return (a + b) % MOD; }

inline LL sub(LL a, LL b) { return (a - b + MOD) % MOD; }

inline LL mul(LL a, LL b) { return a * b % MOD; }

LL f[200010];

LL Inverse(LL a, LL p = MOD) {
  if (a == 1) return 1;
  return sub(0, mul(p / a, Inverse(p % a, p)));
}

LL C(LL a, LL b) {
  return mul(mul(f[a], Inverse(f[b])), Inverse(f[a - b]));
}

struct Warp {
  int sx, sy, tx, ty;

  bool operator<(const Warp &w) const {
    if (sx != w.sx) return sx < w.sx;
    return sy < w.sy;
  }
} w[1010];

LL d[1010];
int m, n, k;

LL Gao(LL sx, LL sy, LL tx, LL ty) {
  if (sx > tx || sy > ty) return 0;
//  printf("%lld %lld %lld %lld\n", sx, sy, tx, ty);
  return C(tx - sx + ty - sy, tx - sx);
}

int main() {
  f[0] = 1;
  for (LL i = 1; i <= 200000; ++i) {
    f[i] = mul(f[i - 1], i);
  }
  while (scanf("%d%d%d", &m, &n, &k) != EOF && m + n + k > 0) {
    for (int i = 0; i < k; ++i) {
      scanf("%d%d%d%d", &w[i].sx, &w[i].sy, &w[i].tx, &w[i].ty);
      --w[i].sx;
      --w[i].sy;
      --w[i].tx;
      --w[i].ty;
    }
    memset(d, 0, sizeof(d));
    sort(w, w + k);
    w[k].sx = m - 1;
    w[k].sy = n - 1;
    for (int i = 0; i <= k; ++i) {
      d[i] = C(w[i].sx + w[i].sy, w[i].sx);
//      printf("%d %lld\n", i, d[i]);
      for (int j = 0; j < i; ++j) {
//        printf("--%d %d\n", i, j);
        d[i] = add(d[i],
                   mul(d[j],
                       sub(Gao(w[j].tx, w[j].ty, w[i].sx, w[i].sy),
                           Gao(w[j].sx, w[j].sy, w[i].sx, w[i].sy))));
//        printf("--%d %d\n", i, j);
      }
//      printf("%d %lld\n", i, d[i]);
    }
    printf("%lld\n", d[k]);
  }

  return 0;
}
accuracy: 1
time_ms: 870
memory_kb: 4344
final_rank: 12

code_snippet: #include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const LL P = 1000000007LL;

int exgcd(int a, int b, int &x, int &y)
{
	if (b == 0)
	{
		x = 1;
		y = 0;
		return a;
	}
	else
	{
		int t = exgcd(b, a % b, y, x);
		y -= a / b * x;
		return t;
	}
}

int inv(int a)
{
	int x, y;
	exgcd(a, P, x, y);
	return (x % P + P) % P;
}

LL fac[200010];

void factorial(void)
{
	fac[0] = 1;
	for (int i = 1; i <= 200000; ++i)
	{
		fac[i] = fac[i - 1] * i;

		if (fac[i] >= P)
			fac[i] %= P;
	}
}

class warp
{
public:
	int sx, sy;
	int ex, ey;

	warp(void) {};
	warp(int _sx, int _sy, int _ex, int _ey) :
		sx(_sx), sy(_sy), ex(_ex), ey(_ey) {};

	friend bool operator < (const warp &a, const warp &b)
	{
		if (a.sx != b.sx)
			return a.sx < b.sx;
		else
			return a.sy < b.sy;
	}
};

int n, m, k;

LL dp[100005];

warp warps[100005];

LL calc(int a, int b)
{
	if (a < 0 || b < 0)return 0LL;
	if (a == 0 || b == 0)return 1LL;
	return fac[a + b] * inv(fac[a]) % P * inv(fac[b]) % P;
}

signed main(void)
{
	factorial();

	while (cin >> n >> m >> k, n || m || k)
	{
		for (int i = 1; i <= k; ++i)
		{
			int sx, sy, ex, ey;
			cin >> sx >> sy >> ex >> ey;
			warps[i] = warp(sx, sy, ex, ey);
		}

		memset(dp, 0, sizeof(dp));

		sort(warps + 1, warps + 1 + k);

		warps[++k] = warp(n, m, n, m);

		for (int i = 1; i <= k; ++i)
		{
			dp[i] = calc(warps[i].sx - 1, warps[i].sy - 1);

			for (int j = 1; j < i; ++j)
			{
				dp[i] += (calc(warps[i].sx - warps[j].ex, warps[i].sy - warps[j].ey) * dp[j]) % P;
				dp[i] -= (calc(warps[i].sx - warps[j].sx, warps[i].sy - warps[j].sy) * dp[j]) % P;
				dp[i] = (dp[i] % P + P) % P;
			}
		}

		cout << dp[k] << endl;
	}

//	system("pause");
}
accuracy: 1
time_ms: 80
memory_kb: 5396
final_rank: 2

code_snippet: #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>
 
using namespace std;

/* constant */

const int MAX_N = 100000;
const int MAX_M = 100000;
const int MAX_K = 1000;

const int MAX_F = MAX_N + MAX_M;
const long long MOD = 1000000007;

/* typedef */

typedef long long ll;

struct WH {
  int x0, y0, x1, y1;
  WH() {}
  WH(int _x0, int _y0, int _x1, int _y1): x0(_x0), y0(_y0), x1(_x1), y1(_y1) {}
  bool operator<(const WH& w) const {
    return x0 < w.x0 || (x0 == w.x0 && y0 < w.y0);
  }
};

/* global variables */

int n, m, k;
WH whs[MAX_K];
ll facts[MAX_F + 1], ifacts[MAX_F + 1];
ll dp[MAX_K];

/* subroutines */

ll powmod(ll a, int b) {	// a^b
  ll p = 1;
  while (b > 0) {
    if (b & 1) p = (p * a) % MOD;
    a = (a * a) % MOD;
    b >>= 1;
  }
  return p;
}

ll comb(ll a, ll b) {	// a_C_b (a >= b)
  ll f0 = facts[a], if0 = ifacts[b], if1 = ifacts[a - b];
  return (((f0 * if0) % MOD) * if1) % MOD;
}

ll f(ll x0, ll y0, ll x1, ll y1) {
  ll dx = x1 - x0, dy = y1 - y0;
  return (dx < 0 || dy < 0) ? 0LL : comb(dx + dy, dx);
}

/* main */

int main() {
  facts[0] = ifacts[0] = 1;
  for (ll i = 1; i <= MAX_F; i++) {
    facts[i] = (facts[i - 1] * i) % MOD;
    ifacts[i] = powmod(facts[i], MOD - 2);
  }

  for (;;) {
    cin >> n >> m >> k;
    if (n == 0) break;

    for (int i = 0; i < k; i++)
      cin >> whs[i].x0 >> whs[i].y0 >> whs[i].x1 >> whs[i].y1;
    sort(whs, whs + k);

    for (int i = 0; i < k; i++) {
      dp[i] = f(1, 1, whs[i].x0, whs[i].y0);

      for (int j = 0; j < i; j++) {
	ll df =
	  (f(whs[j].x1, whs[j].y1, whs[i].x0, whs[i].y0) -
	   f(whs[j].x0, whs[j].y0, whs[i].x0, whs[i].y0) + MOD) % MOD;
	dp[i]  = (dp[i] + (dp[j] * df) % MOD) % MOD;
      }
    }

    ll count = f(1, 1, n, m);

    for (int i = 0; i < k; i++) {
      ll df =
	(f(whs[i].x1, whs[i].y1, n, m) -
	 f(whs[i].x0, whs[i].y0, n, m) + MOD) % MOD;
      count = (count + (dp[i] * df) % MOD) % MOD;
    }

    cout << count << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4308
final_rank: 1

code_snippet: #include<stdio.h>
#include<algorithm>
using namespace std;
int mod=1000000007;
int X1[1100];
int Y1[1100];
int X2[1100];
int Y2[1100];
pair<pair<int,int>,pair<int,int> > p[1100];
long long fact[210000];
long long inv[210000];
long long factinv[210000];
long long dp[1100];
long long getinv(long long a){
	int b=mod-2;
	long long ret=1;
	long long now=a;
	while(b){
		if(b%2)ret=ret*now%mod;
		b/=2;
		now=now*now%mod;
	}
	//printf("%lld: %lld\n",a,ret);
	return ret;
}
long long C(long long n,long long k){
	if(n<0||k<0)return 0;
	n+=k;
	return fact[n]*factinv[k]%mod*factinv[n-k]%mod;
}
int main(){
	int a,b,c;
	fact[0]=1;
	for(int i=1;i<210000;i++)fact[i]=fact[i-1]*i%mod;
	inv[1]=1;
	for(int i=2;i<210000;i++)inv[i]=(mod-(mod/i)*inv[mod%i]%mod)%mod;
	factinv[0]=1;
	for(int i=1;i<210000;i++)factinv[i]=factinv[i-1]*inv[i]%mod;
	while(scanf("%d%d%d",&a,&b,&c),a){
		for(int i=1;i<=c;i++){
			scanf("%d%d%d%d",X1+i,Y1+i,X2+i,Y2+i);
			X1[i]--;X2[i]--;Y1[i]--;Y2[i]--;
			p[i]=make_pair(make_pair(X1[i],Y1[i]),make_pair(X2[i],Y2[i]));
		}
		std::sort(p+1,p+c+1);
		a--;b--;
		for(int i=0;i<c+2;i++)dp[i]=0;
		for(int i=1;i<=c;i++){
			int row=p[i].first.first;
			int col=p[i].first.second;
			dp[i]=C(row,col);
			for(int j=1;j<i;j++){
				//if(row<p[j].second.first||col<p[j].second.second)continue;
				dp[i]=(dp[i]+dp[j]*(mod+C(row-p[j].second.first,col-p[j].second.second)-C(row-p[j].first.first,col-p[j].first.second)))%mod;
			}
		}
		long long ret=C(a,b);
		for(int i=1;i<=c;i++)ret=(ret+dp[i]*(mod+C(a-p[i].second.first,b-p[i].second.second)-C(a-p[i].first.first,b-p[i].first.second)))%mod;
		printf("%lld\n",ret);
	}
}
accuracy: 1
time_ms: 80
memory_kb: 5996
final_rank: 4

code_snippet: #include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long int64;
const int64 MOD = (int64)( 1e9 + 7 );

const int MAX_N = int(1e5);
const int MAX_K = int(1e3);

struct WarpHole {
	int sy, sx, gy, gx;

	WarpHole(){}
	WarpHole(int sy, int sx, int gy, int gx):
		sy(sy), sx(sx), gy(gy), gx(gx)
	{}
};

bool operator< (const WarpHole& lhs, const WarpHole& rhs) {
	return make_pair(lhs.sy, lhs.sx) != make_pair(rhs.sy, rhs.sx) ?
			make_pair(lhs.sy, lhs.sx) < make_pair(rhs.sy, rhs.sx) :
			make_pair(lhs.gy, lhs.gx) != make_pair(rhs.gy, rhs.gx);
}

int N, M, K;
int64 fact[2*MAX_N + 1], invFact[2*MAX_N + 1];
WarpHole warps[MAX_K + 1];
bool visited[MAX_K + 1][MAX_K + 1];
int64 memo[MAX_K + 1][MAX_K + 1];

int64 calcPow(int64 x, int64 n, int64 mod = MOD) {
	int64 ret = 1;
	for (; n; n >>= 1, x = x * x % mod) if (n&1) {
		ret = ret * x % mod;
	}
	return ret;
}


int64 getComb(int n, int k) {
	return fact[n] * invFact[n-k] % MOD * invFact[k] % MOD;
}

int64 getWay(int y, int x) {
	if (y < 0 || x < 0) {
		return 0;
	}
	return getComb(y + x, x);
}

void prepare() {
	fact[0] = invFact[0] = 1;
	for (int i = 0; i < 2*MAX_N; ++i) {
		fact[i+1] = (i + 1) * fact[i] % MOD;
		invFact[i+1] = calcPow(fact[i+1], MOD - 2, MOD);
	}
}

bool init() {
	scanf("%d%d%d", &N, &M, &K);
	for (int i = 0; i < K; ++i) {
		int sy, sx, gy, gx;
		scanf("%d%d%d%d", &sy, &sx, &gy, &gx);
		warps[i] = WarpHole(sy,sx,gy,gx);
	}

	memset(visited, false, sizeof(visited));
	return N > 0;
}

//[0,k)までのワープホールが機能しているときの、
//(1,1)からt番目のワープホールの入り口までの経路の個数を返す
int64 rec(const int k, const int t) {
	//memorize
	if (visited[k][t]) {
		return memo[k][t];
	}
	visited[k][t] = true;

	int64& ret = memo[k][t];

	//base
	if ( k == 0 ) {
		return ret = getWay(warps[t].sy - 1, warps[t].sx - 1);
	}

	//calc
	const int64 inOut = getWay(warps[t].sy - warps[k-1].sy, warps[t].sx - warps[k-1].sx),
			outOut = getWay(warps[t].sy - warps[k-1].gy, warps[t].sx - warps[k-1].gx);
	ret = (rec(k-1, t) - rec(k-1,k-1) * (inOut - outOut) % MOD + MOD) % MOD;

	return ret;
}

int solve() {
	
	for (int i = 0; i < K - 1; ++i) {
		swap(warps[i], *min_element(warps + i, warps + K));
	}
	warps[K] = WarpHole(N, M, N, M);

	return int(rec(K, K));
}

int main() {
	prepare();
	for (;init();) {
		printf("%d\n", solve());
	}
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 13060
final_rank: 13