Codeforces Round #697 (Div. 3) G - Strange Beauty

题目链接在这里:链接
对于这一道题其实主要思想当然是dp了,不过有个问题那就是dp的时候不容易找到dp前的下标所以可以想到的办法利用一个新数组存储下标(ptr数组),dp数组另做处理,这样双线并行即可。
而对于本题来说,主要思路当然是找到对于a[i]来说的在j=(1,i-1)最近且最长子序列,子序列满足的条件为a[m]%(a[m-1]-1)==0(当然前提条件是事先对数组进行了排序)那么状态转移方程就变成了

		**ans[i]=max(ans[i],ans[j]+1)**		

不过可惜的是这样的复杂度是O(n2),显然太大了,需要寻求优化
接下来想如何达到最好的优化,不难想到a[j]必然是a[i]的因子,所以直接在a[i]的因子里寻找合适的k=a[j],同时a[i]%k=0,那么复杂度就变成了O(n*sqrt(n));复杂度直线下降,那么怎么寻找合适的k呢,这就需要用到前面说的ptr下标数组了(前提条件也很明确:不会出现重复的数字),下面是代码:

#include<cstdio>
#include<algorithm>
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
const int MAX_N=2e5+10;
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,i,a[MAX_N],ans[MAX_N]={0},p[MAX_N]={0};
		//a数组用来存输入,ans数组用于dp找下标
		//p数组即为ptr指针用来存储一直下标的j的地址 
		int MAX=0,ma;
		if(n==1){printf("0\n");continue;}
		scanf("%d",&n);
		for(i=1;i<=n;i++){scanf("%d",&a[i]);}
		sort(a+1,a+n+1);//排序当然是必要的啦 
		int ptr=1;
		for(i=1;i<=n;i++){
			ans[i]=1;
			for(int j=1;j*j<=a[i];j++){
				if(a[i]%j!=0){continue;}
				ptr=a[i]/j;//先暂存一下下标地址
				ans[i]=max(max(ans[i],ans[p[j]]+1),ans[p[ptr]]+1);
			}
			p[a[i]]=i;
			MAX=max(MAX,ans[i]);
//此处的MAX即为这个数组中出现beatiful number的最大值 
		}
		printf("%d\n",n-MAX);	
	}
	return 0;
} 

一切结束,题目不难就是有一点点费脑筋,思路很重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值