codeforces #290 div1 B(DP / 暴力)
2015-02-03 16:12:22
思路:比赛中用暴力过掉的....后来发现正解是DP...
First,我们发现只要找出k个数,使得Gcd(num1,num2,...,numk) = 1,就能达到每一个点。
简证:如果我们只考虑两个数x,y。那么若 ax + by = 1 有整数解组a,b,那么就能达到每一个点。
那么有贝祖定理:(a,b)代表最大公因数,则设a,b是不全为零的整数,则存在整数x,y,使得ax+by=(a,b)
所以我们只要使得gcd(a,b)== 1即可。拓展到k个数的情况就是使得Gcd(num1,num2...numk) = 1
Second,YY到gcd的个数应该不会很多,所以就开一个set,从1~n逐个考虑每个数,先将第i个数与set里面的所有数求一遍gcd,然后再把自己加入set... 以此类推。
关于记录最优解,可以用map... (暴力过掉辣... 出题人真良心)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=1;i<=(n);++i) 17 #define REV(i,n) for(int i=(n);i>=1;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define MP(a,b) make_pair(a,b) 21 22 typedef long long ll; 23 typedef pair<int,int> pii; 24 const int INF = (1 << 30) - 1; 25 26 set<int> st; 27 map<int,int> mp; 28 29 int Gcd(int a,int b){ 30 return b == 0 ? a : Gcd(b,a % b); 31 } 32 33 int n,l[310],c[310]; 34 35 int main(){ 36 scanf("%d",&n); 37 REP(i,n) scanf("%d",&l[i]); 38 REP(i,n) scanf("%d",&c[i]); 39 REP(i,n){ 40 set<int>::iterator it; 41 for(it = st.begin(); it != st.end(); ++it){ 42 int g = Gcd(l[i],(*it)); 43 st.insert(g); 44 if(mp.find(g) == mp.end()) 45 mp[g] = mp[(*it)] + c[i]; 46 else 47 mp[g] = min(mp[g],mp[(*it)] + c[i]); 48 } 49 st.insert(l[i]); 50 if(mp.find(l[i]) == mp.end()) 51 mp[l[i]] = c[i]; 52 else 53 mp[l[i]] = min(mp[l[i]],c[i]); 54 } 55 if(mp[1] == 0) printf("-1\n"); 56 else printf("%d\n",mp[1]); 57 return 0; 58 }