bzoj2118
最短路
很早以前做的了
数据范围太大,不能直接算
mn=min(a[i])
算出d[i]表示sum%mn=i最小能构成的数,这个用最短路就行了,然后计算d[i],d[i]+mn的个数统计答案
#include<bits/stdc++.h> using namespace std; const int N = 6e6 + 5; int n; long long l, r, mn = 0x3f3f3f3f; long long a[20], d[N]; int main() { scanf("%d%lld%lld", &n, &l, &r); for(int i = 1; i <= n; ++i) { scanf("%d", &a[i]); mn = min(mn, a[i]); } priority_queue<pair<long long, int>, vector<pair<long long, int> >, greater<pair<long long, int> > > q; memset(d, 0x3f3f, sizeof(d)); d[0] = 0; q.push({0, 0}); while(!q.empty()) { pair<int, int> o = q.top(); q.pop(); int u = o.second; if(d[u] < o.first) continue; for(int i = 1; i <= n; ++i) { int v = (u + a[i]) % mn; if(d[v] <= d[u] + a[i]) continue; d[v] = d[u] + a[i]; q.push({d[v], v}); } } --l; long long ans = 0; for(int i = 0; i < mn; ++i) { if(d[i] <= r) ans += (r - d[i]) / mn + 1; if(d[i] <= l) ans -= (l - d[i]) / mn + 1; } printf("%lld\n", ans); return 0; }