做此题会有一种误区:一个数的最优方案一定是不断地将此数的质因子乘上去。
反例很容易就找到了:20=2^2*5^1。用上面的办法得到的步数应是2+1+5=8,而事实上只需要7就够了——不断把b加到5,在b=4或5时乘到a上,一共需要1+1+5=7
这怎么做啊?
用f[i]表示得到i所需要的最少步数。本来我想先计算j<i,用最有的f[j]来推导f[i],糊里糊涂的绕了进去,没找到正确的递推方式
后来膜拜了别人的程序才发现这个递推方式比较奇(you)葩(mei)。
从小到大枚举b的最终值(恍然大悟!!!),这基础上用最优的i/k来得到i。
yy一下可以发现这样是无后效性的。。。。。
——归根到底还是自己弱
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int l,r,p,prime[100],tot,ans;
int f[4000000],a[4000000],n,i,j,k;
bool check[100], flag[4000000];
void init(){
for (int i=2;i<p;i++){
if (!check[i]) prime[++tot]=i;
for (int j=1;j<=tot;j++){
if (prime[j]*i>=p) break;
check[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
}
void dfs(int num,int s,int x){
a[++n]=num;
for (int i=s;i<=tot;i++){
if (num>x/prime[i]) break;
dfs(num*prime[i],i,x);
}
}
int main(){
freopen("261E.in","r",stdin);
freopen("261E.out","w",stdout);
scanf("%d%d%d",&l,&r,&p);
init();
dfs(1,1,r);
sort(a+1,a+n+1);
memset(f,127/2,sizeof(f));
f[1]=0;
for (i=2;i<p;i++){
for (j=1,k=1;j<=n;j++)
if (a[j]%i==0){
while (a[k]<a[j]/i) k++;
f[j]=min(f[j],f[k]+1);
if (f[j]+i<=p) flag[j]=1;
}
}
for (i=1;i<=n;i++)
if (a[i]>=l && flag[i]) ans++;
//{printf("%d\n",a[i]);ans++;}
printf("%d\n",ans);
return 0;
}