【Cf #290 B】Fox And Jumping(dp,扩展gcd)
根据裴蜀定理,当且仅当选出来的集合的L[i]的gcd等于1时,才能表示任何数。
考虑普通的dp,dp[i][j]表示前i个数gcd为j的最少花费,j比较大,但状态数不多,拿个map转移就好了。
$ \bigodot $ 技巧&套路:
- 裴蜀定理,gcd为1表示任何数。
- 当状态数不多的时候,map暴力转移dp。
#include <bits/stdc++.h> using namespace std; void Work(int &x) { for (int i = 2; i * i <= x; ++i) { while (x % (i * i) == 0) { x /= i; } } } void Insert(map<int, int> &mp, int a, int b) { auto p = mp.find(a); if (p != mp.end()) { p->second = min(p->second, b); } else { mp[a] = b; } } int main() { int n; cin >> n; vector<int> a(n), b(n); for (int i = 0; i < n; ++i) { cin >> a[i]; Work(a[i]); } for (int i = 0; i < n; ++i) { cin >> b[i]; } map<int, int> mp; mp[0] = 0; for (int i = 0; i < n; ++i) { cerr << "deal : " << i << endl; map<int, int> np = mp; for (auto e : mp) { Insert(np, __gcd(e.first, a[i]), e.second + b[i]); } mp = np; } cout << (mp.find(1) != mp.end()? mp[1] : -1) << endl; return 0; }