2118: 墨墨的等式

2118: 墨墨的等式

https://www.lydsy.com/JudgeOnline/problem.php?id=2118

分析:

  最短路。

  题意就是判断[L,R]内多少数,可以被许多个a1,a2,a3...构成。设最小的Mi = min{ai}。L,R<=1e12

  直接枚举肯定超时,那么换个方法枚举。

  考虑一个能构成的数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 }

 

posted @ 2018-09-26 18:16  MJT12044  阅读(209)  评论(0编辑  收藏  举报