中文题
想法:
那么怎么办?
我们不发现石头的数目很小
s < t时, s和t一定会重合(当距离为lcm(s,t)即s,t的最小公倍数时) 而这以后的每个点都可以到达, 所以我们只需将每两个石头超过 s x t 的距离缩成s x t 就可以了
为什么可以这样缩?
因为我们关注的只是经过的石头的数目,s < t时, s和t一定会重合(当距离为lcm(s,t)即s,t的最小公倍数时) 而这以后的每个点都可以到达
最后再注意特判一下 s == t 的时候
#pragma GCC optimize(3,"Ofast","inline")//O3优化 #pragma GCC optimize(2)//O2优化 #include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #include <cstring> #define LL long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f const double eps = 1e-10; const int maxn = 2e5 + 10; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; int f[maxn]; int stone[maxn],new_stone[maxn],vis[maxn]; int main() { ios::sync_with_stdio(false); int L; cin >> L; int l,r,n; cin >> l >> r >> n; if (l == r) { int cnt = 0; for (int i = 1;i <= n;i++) { cin >> stone[i]; if (stone[i] % l == 0) cnt++; } cout << cnt << endl; return 0; } for (int i = 1;i <= n;i++) cin >> stone[i]; sort(stone+1,stone+1+n); int p = l * r; for (int i = 1;i <= n;i++) { int d = stone[i] - stone[i-1]; if (d >= p) d = p; new_stone[i] = new_stone[i-1] + d; vis[new_stone[i]] = 1; } L = new_stone[n] + p; memset(f,0x3f,sizeof(f)); f[0] = 0; for (int i = 1;i <= L;i++) { for (int j = l;j <= r;j++) { if (i >= j) { if (vis[i]) f[i] = min(f[i],f[i-j]+1); else f[i] = min(f[i],f[i-j]); } } } int ans = INF; for (int i = new_stone[n];i <= L;i++) ans = min(ans,f[i]); cout << ans << endl; return 0; }