2118: 墨墨的等式
阿新 • • 發佈:2018-09-26
ret long space name 我們 tchar 分析 out ron
2118: 墨墨的等式
https://www.lydsy.com/JudgeOnline/problem.php?id=2118
分析:
最短路。
題意就是判斷[L,R]內多少數,可以被許多個a1,a2,a3...構成。設最小的Mi = min{ai}。
直接枚舉肯定超時,那麽換個方法枚舉。
考慮一個能構成的數b,它一定可以分解為$b = k \times M_i + r, \ r<M_i$。而且$b + M_i$也是可以構成的。所以我們可以找到最小的%Mi=r的數,比它大的%Mi=r的數可以直接算了。
考慮如何計算最小的,%Mi=r的數:建一張無向圖,共Mi個點,u表示%Mi=u點。dis[u]為最小的%Mi=u的數。那麽可以跑最短路處理處dis[u](即我們要求的)。
然後就可以直接計算了。可以計算出小於等於R的減去小於等於L-1的。
設$dis[r]=k \times Mi + r$,那麽小於等於R的就是$(R-dis[r])/M_i+1$,就是k可以是多少。
代碼:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8#include<vector> 9 #include<queue> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f;17 } 18 19 const LL INF = 1e18; 20 int a[20], n, Mi = 1e9; 21 LL dis[500005]; 22 bool vis[500005]; 23 24 #define pa pair<LL,int> 25 #define mp(a,b) make_pair(a,b) 26 27 priority_queue< pa, vector< pa >, greater< pa > > q; 28 29 void Dijkstra() { 30 for (int i=0; i<Mi; ++i) 31 dis[i] = INF, vis[i] = false; 32 q.push(mp(dis[0] = 0, 0)); 33 while (!q.empty()) { 34 int u = q.top().second; q.pop(); 35 if (vis[u]) continue; 36 vis[u] = true; 37 for (int i=1; i<=n; ++i) { 38 int v = (u + a[i]) % Mi; 39 if (dis[v] > dis[u] + a[i]) { 40 dis[v] = dis[u] + a[i]; 41 q.push(mp(dis[v], v)); 42 } 43 } 44 } 45 } 46 LL Calc(int i,LL x) { 47 if (dis[i] > x) return 0; 48 x -= dis[i]; 49 return x / Mi + 1; 50 } 51 int main() { 52 LL L, R; 53 cin >> n >> L >> R; 54 for (int i=1; i<=n; ++i) cin >> a[i], Mi = min(Mi, a[i]); 55 Dijkstra(); 56 LL Ans = 0; 57 for (int i=0; i<Mi; ++i) 58 if (dis[i] <= R) 59 Ans += Calc(i, R) - Calc(i, L - 1); 60 cout << Ans; 61 return 0; 62 }
2118: 墨墨的等式