BZOJ2118 墨墨的等式(同餘最短路)

Description

給定 a1ana_1 \sim a_nBB 的取值範圍 [l,r][l,r]。求有多少個 BB 滿足有非負整數 x1xnx_1 \sim x_n 使得 B=i=1naixiB = \sum_{i = 1}^n a_ix_i。時間限制 10s。

1n12,0ai5×105,1lr10121 \leq n \leq 12, 0 \leq a_i \leq 5 \times 10^5, 1 \leq l \leq r \leq 10^{12}

Solution

大大凱的疑惑? 前版本爲小凱的疑惑,跳樓機。

用最小的 aia_i 作爲模數 pp。如果一個 BB 有解那麼 Bmodp+k×pB \bmod p +k \times p 也有解,其中 kk 是一個非負整數,它們同餘。

所以用 disidis_ia2ana_2 \sim a_n 跑出最小解 BB 滿足 Bmodp=iB \bmod p = i。可以跑最短路求出。那麼對於每一個 ii,看看能加 pp 得到多少答案,根據加法原理將所有 ii 答案相加。

點有 p1p-1 個而邊的規模爲 n×pn \times p,所以時間複雜度爲 O(nplognp)O(np \log np)。可以用配對堆或斐波那契堆優化到 O(nlogn+np)O(n \log n + np)。我用的 pb_ds 自帶的配對堆,但是因爲 10s 的時限用 priority_queue 也行。好像 spfa 也比較快。

Code

#include <bits/stdc++.h>
#include <ext/pb_ds/priority_queue.hpp>
#define int long long
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef __gnu_pbds :: priority_queue <pair<int, int>, greater<pair<int, int> > ,pairing_heap_tag> pair_heap;
const int N = 1e6 + 5, M = 1e7 + 5, INF = 0x3f3f3f3f;
inline int read() {
	int x = 0, f = 0; char ch = 0;
	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return f ? -x : x;
}
int a[N];
int dis[N], n, l, r;
pair_heap :: point_iterator id[N];
void Dijkstra() {
	pair_heap q; memset(dis, 0x7f, sizeof(dis));
	dis[0] = 0; id[0] = q.push(make_pair(0, 0));
	while(!q.empty()) {
		int x = q.top().second; q.pop();
		for (int j = 2; j <= n; j++) {
			int y = (x + a[j]) % a[1];
			if (dis[y] > dis[x] + a[j]) {
				dis[y] = dis[x] + a[j];
				if (id[y] != NULL) q.modify(id[y], make_pair(dis[y], y));
				else id[y] = q.push(make_pair(dis[y], y));
			}
		}
		
	}
}
signed main() {
	n = read(), l = read() - 1, r = read();
	for (int i = 1; i <= n; i++) a[i] = read();
	sort(a + 1, a + n + 1);
	Dijkstra();
	int ans = 0;
	for (int i = 0; i < a[1]; i++) {
		if (dis[i] <= l) ans -= (l - dis[i]) / a[1] + 1;
		if (dis[i] <= r) ans += (r - dis[i]) / a[1] + 1;
	}
	printf("%lld\n", ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章