Description
給定 和 的取值範圍 。求有多少個 滿足有非負整數 使得 。時間限制 10s。
。
Solution
大大凱的疑惑? 前版本爲小凱的疑惑,跳樓機。
用最小的 作爲模數 。如果一個 有解那麼 也有解,其中 是一個非負整數,它們同餘。
所以用 爲 跑出最小解 滿足 。可以跑最短路求出。那麼對於每一個 ,看看能加 得到多少答案,根據加法原理將所有 答案相加。
點有 個而邊的規模爲 ,所以時間複雜度爲 。可以用配對堆或斐波那契堆優化到 。我用的 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;
}