xay loves count(思维+复杂度优化)

xay loves count

在这里插入图片描述
在这里插入图片描述

题目大意,给定一个序列,求其中有多少满足ai*aj=ak的可能性!

思路:n的范围最大是1e6,要是暴力的话复杂度是n^3,明显不行!

ai范围也在1e6,因此很容易想到当可以通过空间复杂度来优化时间复杂度!!即运用vis判断ai*aj的值是否存在!!那么此时我们将复杂度优化到了n^2(只需要循环i与j)。但显然还会超时!

接下来是最重要的,发现对任意数列,a1,a2,a3…an, 在循环i的时候只需要到sqrt(an),往后i,j只是重复出现,因此复杂度就能优化到O(n*sqrt(n)),即可满足复杂度!!!

其实就是两步简化的过程!!!上代码!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
ll vis[N];
ll cnt[N];
int main(){
	memset(vis,0,sizeof(vis));
	ll n,pos=0;
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		ll a;
		scanf("%lld",&a);
		if(!vis[a]) cnt[++pos]=a;
		vis[a]++; 
	}
	
	ll res=0;
	sort(cnt+1,cnt+pos+1);//排序
	ll m=sqrt(cnt[pos]);//找到需要循环到的数的最大值
	ll mpos=lower_bound(cnt+1,cnt+pos+1,m)-cnt;//找出i需要循环到的下标
	for(int i=1;i<=mpos;i++){
		for(int j=i;j<=pos;j++){
			
			if(cnt[i]*cnt[j]>cnt[pos]) break;//剪枝 ,不加会下标越界
			
			if(vis[cnt[i]*cnt[j]]){
				//cout << cnt[i] << ' ' << cnt[j] << ' ' << cnt[i]*cnt[j] << endl;
				if(i==j) res=res+vis[cnt[i]]*vis[cnt[j]]*vis[cnt[i]*cnt[j]];
				else//i!=j,i和j可以有两种情况 res=res+vis[cnt[i]]*vis[cnt[j]]*vis[cnt[i]*cnt[j]]*2;
			} 
		}
	}
	
	printf("%lld\n",res);
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值