codeforces 261E Maxim and Calculator

做此题会有一种误区:一个数的最优方案一定是不断地将此数的质因子乘上去。

反例很容易就找到了敲打: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;
}


你可能感兴趣的:(递推)