题意:
一条无限长度的路,有n种走的方法,每种方法能让你走 l[i]步,学会该方法花费 c[i];
问你,如果想能走到这条路的所有地方,最少话费是多少,如果不存在输出-1;
题解:
他每次能走的方法是他已经学过的方法的最大公约数,那么就是求对应的gcd,
300个数,最坏的情况应该也就45000个数,所以开50000的数组就足够了。
然后用map记录对应的gcd值,dp[i] 表示 gcd值编号的最小花费。
dp[i.cnt]=min(dp[i.cnt],dp[j]+c[i]);
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
const int maxn=5e4+5;
map<int,int>ma;
int l[305],c[305];
int dp[maxn],g[maxn];
ll gcd(ll a,ll b){
if(b==0) return a;
return gcd(b,a%b);
}
int main(){
int n,cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&l[i]);
for(int i=1;i<=n;++i) scanf("%d",&c[i]);
for(int i=1;i<=n;++i){
for(int j=1;j<=cnt;++j){
int t=gcd(g[j],l[i]);
if(!ma[t]){
g[++cnt]=t;
ma[t]=cnt;
dp[cnt]=dp[j]+c[i];
}else{
dp[ma[t]]=min(dp[ma[t]],dp[j]+c[i]);
}
}
if(!ma[l[i]]){
g[++cnt]=l[i];
ma[l[i]]=cnt;
dp[cnt]=c[i];
}else{
dp[ma[l[i]]]=min(dp[ma[l[i]]],c[i]);
}
}
if(ma[1]==0) puts("-1");
else printf("%d\n",dp[ma[1]]);
return 0;
}