Codeforces Round 993 (Div. 4) E.Insane Problem

Codeforces 题解 - [Codeforces Round 993 (Div. 4) E.Insane Problem]

题目链接

题目描述

Wave 获得了五个整数 \(k\)\(l_1\)\(r_1\)\(l_2\)\(r_2\) 。 Wave 希望你帮助她计算出有序对 \((x, y)\) 的数量,使得以下所有条件都得到满足:

  • \(l_1 \leq x \leq r_1\)
  • \(l_2 \leq y \leq r_2\)
  • 存在一个非负整数 \(n\) 使得 \(\frac{y}{x} = k^n\)

输入格式

Input

The first line contains an integer \(t\) (\(1 \leq t \leq 10^4\)) — the number of test cases.

The only line of each test case contains five integers \(k\), \(l_1\), \(r_1\), \(l_2\), and \(r_2\) (\(2 \leq k \leq 10^9, 1 \leq l_1 \leq r_1 \leq 10^9, 1 \leq l_2 \leq r_2 \leq 10^9\)).

输出格式

Output

For each test case, output the number of matching ordered pairs \((x, y)\) on a new line.

题目大意

给你两个数的区间范围,寻找两个数均在区间范围且符合公式的有序对的数量。

输入

5
2 2 6 2 12
2 1 1000000000 1 1000000000
3 5 7 15 63
1000000000 1 5 6 1000000000
15 17 78 2596 20914861

输出

12
1999999987
6
1
197

解题思路

显然如果枚举x或者y求解有序对的方法, x 和 y 的取值范围[1, 1e9]。 第二个样例就会超时。
但是还有一个n可以进行暴力枚举。
为什么可以暴力枚举n呢?

\[\frac{y}{x} = k^n\tag{1} \]

得到

\[y = x \times k^n \tag{2} \]

x, y的范围是[1, 1e9], k的范围是[2, 1e9]。
考虑到n最大的情况是 y = 1e9, x = 1, k = 2.
也就是说n最大的情况是 n = 30.
我们可以预处理所有\(k^n\), 枚举每个n,对于每个情况的n,我们可以二分最大的x,和最小的x(当然也可以二分y)。
每个时间复杂度是\(log(1e9) ≈ O(30)\).
每个例子的时间复杂度是\(O(log(xR−xL)) ≈ O(30 * log(1e9)) ≈ O(900)\).
总时间复杂度\(O(t×log(xR−xL)) ≈ O(9000000) ≈ O(1e6)\)

代码实现

#include "bits/stdc++.h"
using namespace std;
#define int int64_t
constexpr int Mod = 1e9 + 10;
int powK[50];

void Solution()
{
	int xL, xR, yL, yR, k;
	cin >> k >> xL >> xR >> yL >> yR;
	int pairNum = 0;

	auto Initialization = [&]()
	{
		powK[0] = 1;
		for (int i = 1; i <= 31; ++i)
		{
			powK[i] = powK[i - 1] * k;
			if(powK[i] > Mod) powK[i] = Mod;
		}
		return;
	};
	Initialization();
	auto farLeft = [&](int miD, const int& kN)
	{
		int t = kN * miD;
		// if (t > yR) return false;
		//t < yL return true 太小 增大
		//t == yL return false 尽可能小
		//t > yL return false 还能小
		return t < yL;
	};

	auto farRight = [&](int miD, const int& kN)
	{
		int t = kN * miD;
		// if (t < yL) return true;
		//t > yR return false
		//t == yR return true;
		//t < yR return ture;
		return t <= yR;
	};


	for (int i = 0; i <= 30; ++i)
	{
		int kN = powK[i];
		int lV, rV;
		int lPtr = xL - 1, rPtr = xR + 1;
		while (lPtr + 1 < rPtr)
		{
			int miD = lPtr + rPtr >> 1;
			if (farLeft(miD, kN)) lPtr = miD;
			else rPtr = miD;
		}
		lV = rPtr;
		lPtr = xL - 1, rPtr = xR + 1;
		while (lPtr + 1 < rPtr)
		{
			int miD = lPtr + rPtr >> 1;
			if (farRight(miD, kN)) lPtr = miD;
			else rPtr = miD;
		}
		rV = lPtr;
		// cout << "lV = " << lV << " rV = " << rV << " val = " << rV - lV + 1 << '\n';
		pairNum += rV - lV + 1;
	}
	// cout << "pairNum = ";
	cout << pairNum << '\n';
	return;
}
/*
1
0 1
*/

signed main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	// cout << (1LL * 1 << 1) << '\n';

	int t;
	cin >> t;
	while (t--)
	{
		Solution();
	}
	return 0;
}
/*

1
53 644922653 836907643 264850321 782063425
*/
posted @ 2024-12-28 13:39  MatinalCosmos  阅读(34)  评论(0)    收藏  举报