1 条题解
-
0
抽象思维题。
显然我们可以直接 dp, 为将 变成 0 所需的最小步数。
显然 $f_x=\min _{i=1}^{n} f_{\left \lfloor \frac{x}{a_i} \right \rfloor }+1$,然后状态是 的但是转移不是一个区间,优化不下去了。
发现这玩意显然是单调的。设 为在质数集中最大的能整除 的数。
那么我们有 。发现左端点单调递增,直接队列优化一下即可。
#include<bits/stdc++.h> // #define int long long #define endl '\n' using namespace std; const int mod=998244353,inf=0x3f3f3f3f3f3f3f3f; const int N=1e5+10,M=1e7+10,lim=1e7+1; int n,m,l=1; int a[N],f[M],pm[M]; queue<pair<int,pair<int,int>>>q; signed main() { ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin >> n >> m; for ( int i = 1 ; i <= n ; i++ )cin >> a[i]; sort(a+1,a+1+n); pm[0]=a[n]; for ( int i = 1 ; i <= n ; i++ ) { for ( int j = a[i] ; j <= lim ; j+=a[i] ) { pm[j]=a[i]; } } for ( int i = 1 ; i <= n ; i++ ) { if(1ll*l*a[i]>lim) { l=lim; break; } l*=a[i]; } memset(f,0x3f,sizeof(f)); q.push({0,{0,0}}); for ( int i = 0 ; i < l ; i++ ) { while(q.front().second.second<i)q.pop(); f[i]=q.front().first; q.push({f[i]+1,{i+1,i+pm[i]-1}}); } while(m--) { int x; cin >> x; if(x>=l)cout << "oo\n"; else cout << f[x] << endl; } return 0; } /* n+m 100 >=lcm显然无解 这个好证。 <max显然答案为1,用max进行操作即可 然后答案显然不降 哎呦512M直接dp预处理出1~lcm的全部答案即可 显然每次操作我们要让数尽可能变小 那么我们就有nm做法。 翻了 这个dp我们考虑被动转移 这样的话转移过去就是一个区间。 这玩意不好用数据结构维护 但是我们发现f数组有单调性并且区间左端点单调上升 用一个队列存储所有转移 到i的时候就弹出所有不合法转移(r<i) 然后取出队头进行转移,因为单调性,这样是正确的 瓶颈在于筛最大质因子的过程 似乎是ln,又似乎是loglogn? 跑得飞快就是了 */
- 1
信息
- ID
- 4801
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者