做此题会有一种误区:一个数的最优方案一定是不断地将此数的质因子乘上去。
反例很容易就找到了: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; }