第十二届蓝桥杯省赛:货物摆放

文章介绍了如何通过优化枚举算法来解决计算n的因子贡献的问题。首先避免三重循环,改为两重循环并利用n的因子特性减少复杂度。通过求解n的因子并存储在向量中,然后对因子进行枚举,根据因子之间的关系计算答案。最终得出的答案是2430。

分析:首先可以发现n是一个long long类型的数,如果我们直接三重for循环枚举是绝对不可取的,现在我们考虑一个问题,假如存在x*y*z=n,且x和y以及z均不相同,那么对于这三个数对答案的贡献是多少呢?显然是3!,也就是6,假如存在两个数相同呢?那么贡献就是3,因为这取决于与其他两个数不同的那个数的位置。如果要是三个数均相同,那么答案显然就是1了。所以我们假如我们要枚举三重for循环i,j,k,那么也可以假定i<=j<=k,然后再判断三者之间有几个数是相同的来判断这三个数对答案的贡献。那么我们可以发现枚举两重for循环也是可以的,比如我们枚举i和j,如果n%(i*j)=0,说明存在k=n/i/j使得i*j*k=n成立,那么复杂度会明显减少,枚举第二重循环的时候需要注意我们可以令k等于j来得到k的下界,不然可能会重复记录,细节见代码即可,但是可以发现这样做复杂度还是有点偏高,所以我们来进行最后的优化,我们可以发现上述枚举的数都是n的因子,所以我们完全可以先用O(sqrt(n))的复杂度求出n的因子,然后我们直接对因子进行枚举即可

答案为2430

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=1e5+10;
vector<long long>p;//存n的因子 
int main()
{
	long long n=2021041820210418;
	for(long long i=1;i*i<=n;i++)
	{
		if(n%i!=0) continue;
		p.push_back(i);
		if(i*i!=n) p.push_back(n/i);
	} 
	sort(p.begin(),p.end());
	long long ans=0;
	for(long long i=0;p[i]*p[i]*p[i]<=n;i++)
	for(long long j=i;p[i]*p[j]*p[j]<=n;j++)
	{
		if(n%(p[i]*p[j])!=0) continue;//说明不存在k使得i*j*k=n
		long long k=n/(p[i]*p[j]);
		if(i==k) ans++;//三个数均相同 
		else if(i==j||j==k) ans+=3;//两个数相同 
		else ans+=6;//三个数均不相同 
	}
	printf("%lld\n",ans); 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值