D. Coprime(掐时间复杂度点,思维题,贪心)

文章讨论了一种寻找数组中互质元素最大下标对的问题,通过使用unordered_map存储元素及其下标并采用贪心策略,结合两层循环和__gcd函数,实现了时间复杂度在可接受范围内的解决方案。

题目:

 

输入
6
3
3 2 1
7
1 3 5 2 4 7 7
5
1 2 3 4 5
3
2 2 4
6
5 4 3 15 12 16
5
1 2 2 3 6

输出
6
12
9
-1
10
7

思路:

        这是一道思维题,也有贪心,暴力枚举,在这里是掐着时间复杂度的思维题。

题目意思是 从数组中 找出互质的两个数 它们的下标最大。

所以我们可以在输入的时候标记一下对应元素的下标,然后是顺着标记,这样也是贪心,当出现相同的元素,我们取最大的下标覆盖之前标记的最小下标

又因为 这里元素数据范围是 1000 即(10^3)这里我们再进行两层循环 时间复杂度是 10^6 加上我们的 __gcd ()时间复杂度O(log min(a,b)),最坏情况nlog min(a,b),测试样例 1 <= T <= 10 数据范围 ,我们用 unordered_map 时间复杂度是 O(1),最坏的情况也是 O(n) 这里的 n 是我们的元素数据范围 1000

  整个循环过程,时间复杂度就是10^7 + 1000 + nlog min(a,b)——10^8 + 1000 + nlog min(a,b)之间

没有超过 10^9 所以不会超时,一般来说 超过 10^9 就会超时的

代码详解如下:

#include <iostream>
#include <unordered_map>
#include <algorithm>
#define endl '\n'
#define umap unordered_map
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;

inline void solve()
{

	umap<int, int>r;
	// r 用来标记元素对应的下标
	// 用 unordered_map 效率为 O(1)
	int n = 0;
	int ans = -1;
	cin >> n;
	for (int i = 1, x; i <= n; ++i)
	{
		cin >> x;
		// 标记好下标
		r[x] = i;
	}
	// 因为我们元素的数据范围为 1000 所以直接暴力两层循环
	// 查找我们下标和最大即可  这里的两层循环 效率为 O(n^2)  所以 O(1000 * 1000 == 1e6)
	// 这样是不会超时的,反而如果 用 我们定义的 n  则 O((2 * 1e5) * (2 * 1e5) == 4 * 1e10)就会超时了
	// 再加上 __gcd() 时间复杂度是 O(log min(a,b)) 可以刚刚恰着TLE分界线,差一丢丢就会超时的
	// 这是贪心思维题

	for (int i = 1; i <= 1000; ++i)
	{
		for (int j = 1; j <= 1000; ++j)
		{
			if (__gcd(i, j) == 1 && r[i] && r[j])
			{
				ans = max(ans, r[i] + r[j]);
			}
		}
	}
	cout << ans << endl;
}

int main()
{
	___G;
	int _t;
	cin >> _t;
	while (_t--)
	{
		solve();
	}

	return 0;
}

最后提交:

### 欧拉函数求解公式的时间复杂度分析 对于给定的大于1的自然数 \( n \),通过算术基本定理可将其分解为多个质数的乘积: \[ n = p_1^{\alpha_1} \times p_2^{\alpha_2} \times \ldots \times p_k^{\alpha_k} \] 其中 \( p_i \) 是不同的质因子,\( \alpha_i \geq 1 \)[^4]。 欧拉函数 \( \phi(n) \) 的具体公式如下所示: \[ \phi(n) = n \left(1-\frac{1}{p_1}\right)\left(1-\frac{1}{p_2}\right)...\left(1-\frac{1}{p_k}\right) \] 为了计算该公式的实际时间复杂度,需考虑以下几个方面: #### 质因数分解过程中的时间开销 要应用上述公式,首先需要找到所有的质因子及其对应的指数。这一步骤通常采用试除法完成,即尝试用小于等于 \( \sqrt{n} \) 的所有可能质数去除 \( n \),直到不能再被整除为止。因此,在最坏情况下(比如当 \( n \) 自身是一个大素数),此操作大约会执行约 \( O(\sqrt{n}) \) 步。 #### 迭代相乘部分的时间消耗 一旦获得了全部质因子之后,就可以按照公式依次迭代相乘来获得最终结果。由于这里涉及的是常量次浮运算,这部分的操作次数固定不变,故其时间成本近似为常数级别 \( O(1) \)[^3]。 综上所述,整个过程中主要瓶颈在于第一步——寻找并确认各个质因子的过程;而后续处理则相对简单得多。所以总体来看,利用直接公式求解单个数值的欧拉函数的时间复杂度大致为 \( O(\sqrt{n}) \)。 ```python def euler_phi(n): result = n # Initialize result as n # Consider all prime factors of n and subtract their multiples from result p = 2 while(p * p <= n): if (n % p == 0): # If yes, then update n and result while (n % p == 0): n //= p result -= int(result / p) p += 1 if (n > 1): result -= int(result / n) return result print(euler_phi(10)) # Output should be 4 since there are four numbers less than or equal to 10 that are coprime with it. ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值