P1890 题解
I_have_been_here · · 个人记录
题面
题面分析
这道题很明显可以用数学的方法强力解决,但是在这里
我给大家推荐一种更好的短小精悍的数据结构 ——
方法介绍
也就是说左端点后
根据我们刚才状态定义的解释,我们就可以得到状态转移方程:
这是st表的预处理部分,我们可以得到:
for (int j = 1; j <= 30; j++) { //一定先枚举j
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); //方程
}
}
经过
例题处理
对于这道题,和
Code
#include <bits/stdc++.h>
#define maxn 10005
using namespace std;
int gcd(int x, int y) {
return y == 0 ? x : gcd(y, x % y);
}
int n, m, f[maxn][31];
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
scanf("%d", &f[i][0]);
}
for (int j = 1; j <= 30; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
f[i][j] = gcd(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);//预处理
}
}
for (int i = 1, l, r, k; i <= m; i++) {
scanf("%d %d", &l, &r);
k = log2(r - l + 1);//得到区间长度
printf("%d\n", gcd(f[l][k], f[r - (1 << k) + 1][k]));//查询
}
}