BZOJ 2118 墨墨的不等式 数论 + 最短路 + 计数
1 #include<bits/stdc++.h> 2 #define LL long long 3 const LL INF = 50000000000000000ll; 4 #define maxn 500010 5 using namespace std; 6 LL l, r; 7 LL ans = 0; 8 int n, a[maxn]; 9 LL mi = INF, d[maxn]; 10 LL solve(LL x){ 11 if(x > r) return 0; 12 else if(x >= l){ 13 return ((r - x)/mi + 1ll); 14 } 15 else{ 16 return ((r - x)/mi - (l - 1 - x)/mi); 17 } 18 } 19 void spfa(){ 20 bool vis[maxn]; 21 memset(vis, false, sizeof(vis)); 22 for(int i = 0; i < mi; i ++){ 23 d[i] = INF; 24 } 25 d[0] = 0; 26 vis[0] = true; 27 queue<int> Q; 28 Q.push(0); 29 int p, now; 30 while(!Q.empty()){ 31 p = Q.front(); 32 Q.pop(); 33 vis[p] = false; 34 for(int i = 1; i <= n; i ++){ 35 if(a[i] == mi) continue; 36 now = (p + a[i]) % mi; 37 if(d[now] > d[p] + a[i]){ 38 d[now] = d[p] + a[i]; 39 if(!vis[now]){ 40 vis[now] = true; 41 Q.push(now); 42 } 43 } 44 } 45 } 46 } 47 int main(){ 48 cin >> n >> l >> r; 49 for(int i = 1; i <= n; i ++){ 50 scanf("%d",&a[i]); 51 if(a[i] == 0){ 52 i --, n --; 53 } 54 else 55 mi = min(mi, (LL)a[i]); 56 } 57 if(mi == 1){ 58 cout << (r - l + 1) << endl; 59 return 0; 60 } 61 spfa(); 62 for(int i = 0; i < mi; i ++){ 63 if(d[i] == INF) continue; 64 ans += solve((LL)d[i]); 65 } cout << ans; 66 return 0; 67 }