BZOJ3233: [Ahoi2013]找硬币
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3233
多一点硬币是没有关系的,不用就行了。
然后有一个dp,f[i]=min(f[j]-∑a[k]/i* (i/j-1) )
然后只要枚举i的质因子就可以了。(先线性筛出最大的质因子。。
#include<cstring> #include<iostream> #include<cstdio> #include<queue> #include<cmath> #include<algorithm> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define low(x) (x&(-x)) #define maxn 100500 #define inf int(1e9) #define mm 1000000007 #define ll long long using namespace std; int a[maxn],mn[maxn],pri[maxn],b[maxn],f[maxn],tot,ans,n,mx; ll read(){ ll x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } void getpri(){ rep(i,2,100000) { if (!b[i]) b[i]=1,mn[i]=i,pri[++tot]=i; rep(j,1,tot) if (i*pri[j]<=100000) { b[i*pri[j]]=1; mn[i*pri[j]]=pri[j]; if (i%pri[j]==0) break; } else break; } } int main(){ getpri(); n=read(); rep(i,1,n) a[i]=read(),mx=max(a[i],mx),f[1]+=a[i]; rep(i,1,mx) f[i]=f[1]; ans=f[1]; rep(i,2,mx) { int x=i; while (x>1){ int t=f[i/mn[x]]; rep(j,1,n) t-=a[j]/i*(mn[x]-1); f[i]=min(f[i],t); if (mn[x]==mn[x/mn[x]]) x/=mn[x]; x/=mn[x]; } ans=min(ans,f[i]); } printf("%d\n",ans); return 0; }