제출 #1369839

#제출 시각아이디문제언어결과실행 시간메모리
1369839LOLOLOBoat (APIO16_boat)C++20
0 / 100
3 ms344 KiB
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

long long MOD = 1e9 + 7;

// Hàm tính nghịch đảo modulo để dùng trong tính tổ hợp
long long power(long long base, long long exp) {
    long long res = 1;
    base %= MOD;
    while (exp > 0) {
        if (exp % 2 == 1) res = (res * base) % MOD;
        base = (base * base) % MOD;
        exp /= 2;
    }
    return res;
}

long long modInverse(long long n) {
    return power(n, MOD - 2);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;

    vector<int> a(n + 1), b(n + 1);
    vector<int> coords;
    for (int i = 1; i <= n; i++) {
        cin >> a[i] >> b[i];
        coords.push_back(a[i]);
        coords.push_back(b[i] + 1);
    }

    // Rời rạc hóa các khoảng giá trị
    sort(coords.begin(), coords.end());
    coords.erase(unique(coords.begin(), coords.end()), coords.end());

    int m = coords.size();
    
    // dp[i] là tổng số cách tính đến thời điểm hiện tại cho các trường đã xét
    // pre[i] là tổng dồn của dp để tối ưu hóa việc tính tổng các đoạn trước
    vector<long long> dp(m, 0);
    vector<long long> pre(m, 1); // Trường hợp cơ sở: 1 cách (không gửi gì)
    
    // Tiền xử lý nghịch đảo modulo để tính tổ hợp nhanh
    vector<long long> inv(n + 1);
    for (int i = 1; i <= n; i++) inv[i] = modInverse(i);

    for (int i = 1; i <= n; i++) {
        for (int j = m - 2; j >= 0; j--) {
            int L = coords[j + 1] - coords[j];
            // Nếu đoạn [coords[j], coords[j+1] - 1] nằm trong [a[i], b[i]]
            if (a[i] <= coords[j] && b[i] >= coords[j + 1] - 1) {
                long long ways = L; // Tương ứng C(L, 1)
                long long combinations = L; 
                
                int count = 1; // Số lượng trường chọn gửi thuyền vào đoạn j
                
                // Trường i là trường cuối cùng trong đoạn j
                dp[j] = (dp[j] + combinations * pre[j]) % MOD;

                for (int p = i - 1; p >= 1; p--) {
                    if (a[p] <= coords[j] && b[p] >= coords[j + 1] - 1) {
                        count++;
                        // Công thức tính C(L+count-1, count) dựa trên C(L+count-2, count-1)
                        // C(L+k-1, k) = C(L+k-2, k-1) * (L+k-1) / k
                        combinations = combinations * (L + count - 1) % MOD;
                        combinations = combinations * inv[count] % MOD;
                        
                        dp[j] = (dp[j] + combinations * pre[j]) % MOD;
                    }
                }
            }
        }
        // Cập nhật mảng pre sau khi xét xong trường i
        long long current_sum = 1;
        for (int j = 0; j < m - 1; j++) {
            current_sum = (current_sum + dp[j]) % MOD;
            pre[j + 1] = current_sum;
        }
    }

    long long result = 0;
    for (int j = 0; j < m - 1; j++) {
        result = (result + dp[j]) % MOD;
    }

    cout << result << endl;

    return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…