题解 P2618 【数字工程】
EightSixSun · · 题解
先筛出1~1000000中的所有素数,然后对于每一组数据,从1开始,遍历每一种操作,状态转移方程也就是
dp[i+1]=min(dp[i+1],dp[i]+1)
dp[i*prime[j]]=min(dp[i*prime[j],dp[i]+1)
但是对于同一个n的答案是一样的,所以我们记录下来,下次再遇到n就可以直接输出,如果遇到大于之前所有n的数我们再算,可以节省那么十几ms,不弄也可以过,应该数据比较水。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
int dp[1000001],prime[1000001],pcnt=0,n;
bool isPrime[1000001];
int main()
{
int j;
For(i,2,1000000)
dp[i]=2147483647;
isPrime[1]=1;
For(i,2,1000000)
{
if(!isPrime[i])
{
j=i+i;
prime[++pcnt]=i;
while(j<=1000000)
{
isPrime[j]=1;
j+=i;
}
}
}
while(scanf("%d",&n)!=EOF)
{
if(dp[n]==2147483647)
For(i,1,n)
{
dp[i+1]=min(dp[i]+1,dp[i+1]);
For(j,1,pcnt)
{
if(i*prime[j]>n)
break;
dp[i*prime[j]]=min(dp[i*prime[j]],dp[i]+1);
}
}
cout<<dp[n]<<'\n';
}
return 0;
}