1. 程式人生 > 實用技巧 >一道題目

一道題目

Luogu比賽"小Z的 J-PCS 模擬賽"中有一道題目。(LC 比賽Rank 2 !!!!不愧是我們滴紅太陽!!!太強哩!!!!) OOOOOrz

感覺這道題雖然水但是有點意思。

題意

就是求\(Max(i\) \(mod\) \(a\)) + (\(i\) \(mod\) \(b\))) 限定\(i\) ∈ 區間\([L,R]\)

給出\(a,b\)以及若干個詢問,每個詢問給出詢問區間\([L,R]\)

\(1\) <= \(L,R\) <= \(10^9\) , 詢問個數 <= \(10^6\), \(1\) <= \(a,b\) <= \(1000\)

這道題目的解法

\(GCD求LCM + ST\)表即可

求出\(a,b\)\(LCM\)然後暴力擴充套件,\(LCM(a,b)\) <= \(10^6\),然後對於每個詢問用ST表即可.

時間複雜度:O(\(nlog(n)\) + \(q\) )

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
int A[MAXN];
int Max[MAXN][22];
int gcd(int a,int b)
{
	if(a % b == 0)return b;
	else return gcd(b , a % b);
}

int LCM(int a,int b)
{
	return a*b/gcd(a,b);
}

inline int read()
{
	int x = 0 , flag = 1;
	char ch = getchar();
	for ( ; ch > '9' || ch < '0' ; ch = getchar())if(ch == '-')flag = -1;
	for ( ; ch >= '0' && ch <= '9' ; ch = getchar())x = (x << 3) + (x << 1) + ch - '0';
	return flag * x;
}

int GetMax(int l,int r)
{
	int k = log2(r - l + 1);
	return max(Max[l][k] , Max[r - (1 << k) + 1][k]);
}

int main()
{
	int a,b,n;
	a = read() , b = read();
	n = read();
	int lcm = LCM(a,b);
	for(int i = 1 ; i <= lcm ; i ++)
		A[i] = i % a + i % b,Max[i][0] = A[i];
	for(int j = 1 ; j <= log2(lcm) ; j ++)
		for(int i = 1 ; i + (1 << j) - 1<= lcm ; i ++)
	Max[i][j] = max(Max[i][j - 1] , Max[i + (1 << (j - 1))][j - 1]);
	for(int i = 1 ; i <= n ; i ++)
	{
		int l , r ,ll , rr;
		l = read() , r = read();
		if(r - l >= lcm)
		{
			cout << GetMax(1,lcm) << endl;
			continue;
		}
		ll = l , rr = r;
		l %= lcm;r %= lcm;
		if(l == 0) l = lcm;
		if(r == 0) r = lcm;
		if(l > r)
			cout << max( GetMax(l,lcm) , GetMax(1,r) ) << endl;
		else cout << GetMax( l , r ) << endl;
	}
	return 0;
}