标签:
给出h、x、y、z,求在h以内,x、y、z可以凑出多少个不同的数。
(1≤h≤10^18,1≤x, y, z≤10^5。)
直接做显然不好做。我们考虑取n个y和m个z,然后再加上x、2 * x、3 * x...,显然地,只要对于每种取法,(ny + mz) % x 的值不同的话,就不会有重复。所以我们先求出 d[i] = c 表示通过选y和z使得和模x等于i的最小和c。然后答案就是 ∑0≤i<x (h - d[i]) / x + 1。至于怎么求d[i],可以发现 d[(i + y) % x] = min d[i] + y、d[(i + z) % x] = d[i] + z,明显的最短路模型。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define i64 long long 6 using namespace std; 7 8 const int N = 1e5 + 10; 9 const i64 inf = 1e18 + 1; 10 int x, y, z, inq[N]; 11 i64 h, ans, d[N]; 12 13 queue <int> q; 14 15 void spfa() { 16 for (int i = 0; i < x; i ++) d[i] = inf; 17 d[1] = 1 % x; 18 q.push(1); 19 inq[1] = 1; 20 while (!q.empty()) { 21 int i = q.front(); q.pop(); 22 if (d[i] + y < d[(i + y) % x]) { 23 d[(i + y) % x] = d[i] + y; 24 if (!inq[(i + y) % x]) { 25 inq[(i + y) % x] = 1; 26 q.push((i + y) % x); 27 } 28 } 29 if (d[i] + z < d[(i + z) % x]) { 30 d[(i + z) % x] = d[i] + z; 31 if (!inq[(i + z) % x]) { 32 inq[(i + z) % x] = 1; 33 q.push((i + z) % x); 34 } 35 } 36 inq[i] = 0; 37 } 38 } 39 40 int main() { 41 scanf("%lld", &h); 42 scanf("%d %d %d", &x, &y, &z); 43 spfa(); 44 for (int i = 0; i < x; i ++) if (h > d[i]) ans += (h - d[i]) / x + 1; 45 printf("%lld", ans); 46 return 0; 47 }
标签:
原文地址:http://www.cnblogs.com/awner/p/5796948.html