3233: [Ahoi2013]找硬幣

Description

小蛇是金融部部長。最近她決定製造一系列新的貨幣。假設她要製造的貨幣的面值爲x1,x2,x3… 那麼x1必須爲1,xb必須爲xa的正整數倍(b>a)。例如 1,5,125,250就是一組合法的硬幣序列,而1,5,100,125就不是。不知從哪一天開始,可愛的蛇愛上了一種萌物——兔紙!從此,小蛇便走上了遇上兔紙娃娃就買的不歸路。某天,小蛇看到了N只可愛的兔紙,假設這N 只兔紙的價錢分別是a1,a2…aN。現在小蛇想知道,在哪一組合法的硬幣序列下,買這N只兔紙所需要的硬幣數最少。買兔紙時不能找零。
 
 
 

Input

第一行,一個整數N,表示兔紙的個數
第二行,N個用空格隔開的整數,分別爲N只兔紙的價錢
 
 
 

Output

一行,一個整數,表示最少付的錢幣數。

 
 
 

Sample Input

2
25 102



Sample Output

4

題解:
f[i]表示以i爲最大值的最少硬幣數,
f[i]=min(f[j]-sigma(a[k]/i)*(i/j-1))
a[k]/i就表示這個兔子需要幾個i值的硬幣,這些硬幣值(i/j)個值爲j的硬幣,所以可以少(i/j-1)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100001;
int n;
int a[60];
int prime[N],top=0;
bool v[N];
void ge_pr()
{
	for(int i=2;i<N;i++)
	{
		if(!v[i]) prime[++top]=i;
		for(int j=1;j<=top&&prime[j]*i<N;j++)
		{
			v[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
	}
}
int tot=0,ans,mx=0;
int f[N];
int main()
{
	ge_pr();
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]),tot+=a[i],mx=max(mx,a[i]);
	memset(f,63,sizeof(f));
	ans=f[1]=tot;
	for(int i=2;i<=mx;i++)
	{
		f[i]=tot;
		int p=i;
		for(int j=1;j<=top;j++)
		{
			if(p%prime[j]==0)
			{
				int x=i/prime[j];
				int sum=0;
				for(int u=1;u<=n;u++) sum+=(a[u]/i)*(prime[j]-1);
				f[i]=min(f[i],f[x]-sum);
				while(p%prime[j]==0) p/=prime[j];
				if(p==1) break;
			}
		}
		ans=min(ans,f[i]);
	}
	printf("%d\n",ans);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章