https://vjudge.net/problem/CodeForces-510D
题目可以转化为花最小代价选一些数,然后这些数可以经过加减运算得到1或-1,不然1你就凑不出来,一旦凑出来1,其他的都有了。由贝祖定理,ax+by=gcd(a,b)=1,贝祖定理能推广到n个,ax+by+cz+…=gcd(a,b,c,…)。令m[i]为得到的gcd为i的最小代价,spfa暴力更新,最后输出m[1]
#include <iostream> #include <cstdio> #include <queue> #include <algorithm> #include <cmath> #include <cstring> #include <unordered_map> #define inf 2147483647 #define N 1000010 #define p(a) putchar(a) #define For(i,a,b) for(int i=a;i<=b;++i) using namespace std; int n,k; int L[N],c[N]; queue<int>q; unordered_map<int,int>m; void in(int &x){ int y=1;char c=getchar();x=0; while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();} x*=y; } void o(int x){ if(x<0){p('-');x=-x;} if(x>9)o(x/10); p(x%10+'0'); } int gcd(int a,int b){ return (a%b==0?b:gcd(b,a%b)); } void spfa(){ while(!q.empty()){ int t=q.front();q.pop(); For(i,1,n){ k=gcd(L[i],t); if(!m[k]){ q.push(k); m[k]=m[t]+m[L[i]]; } else m[k]=min(m[k],m[t]+m[L[i]]); } } } signed main(){ in(n); For(i,1,n) in(L[i]); For(i,1,n) in(c[i]); For(i,1,n) if(!m[L[i]]) m[L[i]]=min(m[L[i]],c[i]); else{ q.push(L[i]); m[L[i]]=c[i]; } spfa(); if(m[1]) o(m[1]); else o(-1); return 0; }