您的位置:首页 > 其它

BZOJ3233: [Ahoi2013]找硬币

2016-01-14 22:07 423 查看
题目: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: