做题感悟:开始以为只要把一个数分成尽量相等的两个数相乘就可以了,其实大部分数据都对。
解题思路:如果n是素数则 f [ n ] = f [ n-1]+1 ,否则 遍历n的约数找最小的。f [ n ] = min ( f [ n-1 ]+1,f [ j ] + f [ n / j ] ) .
代码(本人):
#include<stdio.h>
#include<iostream>
#include<map>
#include<string>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std ;
const int MX = 10005 ;
int f[MX] ;
bool is_prime[MX] ;
int prime[MX],num ;
void init()
{
num=0 ;
memset(is_prime,false,sizeof(is_prime)) ;
for(int i=2 ;i<MX ;i++)
{
if(!is_prime[i])
prime[num++]=i ;
for(int j=0 ;j<num&&i*prime[j]<MX ;j++)
{
is_prime[i*prime[j]]=true ;
if(i%prime[j]==0)
break ;
}
}
}
int min(int x,int y)
{
return x < y ? x : y ;
}
void pret()
{
memset(f,0,sizeof(f)) ;
f[1]=1 ; f[2]=2 ; f[3]=3 ; f[4]=4 ;
for(int i=5 ;i<MX ;i++)
if(is_prime[i])
{
f[i]=f[i-1]+1 ;
for(int j=2 ;j<=sqrt(i) ;j++)
if(i%j==0)
f[i]=min(f[i],f[j]+f[i/j]) ;
}
else
f[i]=f[i-1]+1 ;
}
int main()
{
init() ;
pret() ;
int n ;
while(~scanf("%d",&n))
printf("%d\n",f[n]) ;
return 0 ;
}
优代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int dp[10005]={0,1,2,3,4,5,0,0,0};
int main()
{
int n,i,j;
for(i=6;i<10005;i++)
{
dp[i]=dp[i-1]+1;
for(j=2;j*j<=i;j++)
{
if(i%j==0)
{
dp[i]=min(dp[i],dp[j]+dp[i/j]);
}
}
}
while(scanf("%d",&n)!=EOF)
{
printf("%d\n",dp[n]);
}
}