제출 #1062944

#제출 시각아이디문제언어결과실행 시간메모리
1062944vuavisaoTrains (BOI24_trains)C++17
100 / 100
115 ms9868 KiB
#include <bits/stdc++.h>
#pragma GCC optimize("O3", "unroll-loops")
using namespace std;

using ll = long long;

const int N = 100'000 + 10;
const int MOD = 1'000'000'000 + 7;

template <int Module>
class Mint {
private:
	int val;

public:
	Mint() : val(0) {};
	Mint(ll _val) {
		val = _val % Module;
		normalization_effect();
	}

public:
	void normalization_effect() {
		/// [- Module, 2 * Module)
		this->val = this->val + (this->val < 0) * Module - (this->val >= Module) * Module;
	}

	int get_val() const { return this->val; }

	Mint operator-() const { return Mint(-this->val); }

	Mint pw(ll exp) const {
		Mint res = 1;
		Mint base = *this;
		while (exp > 0) {
			if(exp & 1ll) res *= base;
			base *= base;
			exp >>= 1ll;
		}
		return res;
	}

	Mint inv() const {
		/// Module is prime
		/// return 〖val〗^(-1)
		return this->pw(Module - 2);
	}

public:
	Mint& operator+=(const Mint& other) {
		this->val += other.val;
		this->normalization_effect();
		return *this;
	}

	Mint& operator-=(const Mint& other) {
		this->val -= other.val;
		this->normalization_effect();
		return *this;
	}

	Mint& operator*=(const Mint& other) {
		this->val = 1ll * this->val * other.val % Module;
		this->normalization_effect();
		return *this;
	}

	Mint& operator/=(const Mint& other) {
		this->operator*=(other.inv());
		return *this;
	}

	Mint& operator++() { this->operator+=(1); return *this; }
	Mint& operator--() { this->operator-=(1); return *this; }

	Mint operator+(const Mint& other) const {
		Mint res = *this;
		res += other;
		return res;
	}

	Mint operator-(const Mint& other) const {
		Mint res = *this;
		res -= other;
		return res;
	}

	Mint operator*(const Mint& other) const {
		Mint res = *this;
		res *= other;
		return res;
	}

	Mint operator/(const Mint& other) const {
		Mint res = *this;
		res /= other;
		return res;
	}

	bool operator==(const Mint& other) const {
		return (this->val == other.val);
	}

public:
	friend ostream& operator<<(ostream& os, const Mint& other) {
		return os << other.val;
	}
};

using mint = Mint<MOD>;

struct event {
	int idx, dist, mod, type;
	event() : idx(0), dist(0), mod(0), type(0) {};
	event(int _idx, int _dist, int _mod, int _type) : idx(_idx), dist(_dist), mod(_mod), type(_type) {};
};

int n;
int dist[N], cnt[N];

vector<event> events[N];

int sqrt_n;
mint pref[320][320];
mint dp[N];

void solve() {
	cin >> n;
	sqrt_n = sqrt(n);
	for (int i = 1; i <= n; ++ i) {
		cin >> dist[i] >> cnt[i];
		if (cnt[i] == 0 || dist[i] == 0) continue;
		if (dist[i] <= sqrt_n) {
			int first = i + dist[i];
			int last = i + min((n - i) / dist[i], cnt[i]) * dist[i];
			if (first <= n) {
				events[first].push_back(event(i, dist[i], i % dist[i], 1));
			}
			if (last + dist[i] <= n) {
				events[last + dist[i]].push_back(event(i, dist[i], i % dist[i], -1));
			}
		}
	}
	dp[1] = 1;
	for (int i = 1; i <= n; ++ i) {
		for (const auto& [idx, d, mod, sign] : events[i]) {
			// cout << idx << ' ' << d << ' ' << mod << ' ' << sign << '\n';
			pref[d][mod] += mint(sign) * dp[idx];
		}
		for (int dist = 1; dist <= sqrt_n; ++ dist) {
			dp[i] += pref[dist][i % dist];
		}
		if (dist[i] > sqrt_n) {
			for (int j = 1; j <= cnt[i]; ++ j) {
				int nxt = i + j * dist[i];
				if (nxt > n) break;
				dp[nxt] += dp[i];
			}
		}
	}
	mint res = 0;
	for (int i = 1; i <= n; ++ i) {
		// cout << dp[i] << " \n"[i == n];
		res += dp[i];
	}
	cout << res;
}

int32_t main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(nullptr); std::cout.tie(nullptr);
	// int t; cin >> t;
	int t = 1;
	while (t-- > 0) {
		solve();
		cout << '\n';
	}
	return (0 ^ 0);
}

/// Code by vuavisao
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...