zoukankan      html  css  js  c++  java
  • [题解] [JSOI2015] 最大公约数

    题面

    题解

    考虑到固定左端点, 那么所有的区间的 (gcd) 最多只有 (log) 种取值

    证明: 从左至右. 若 (gcd) 变化, 每次至少都会 (/ 2)

    对于每一个左端点二分找这个位置, ST 表查询区间 (gcd)

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    const int N = 1e5 + 5;
    typedef long long ll; 
    using namespace std;
    
    int n, lg[N];
    ll st[20][N], ans; 
    
    template < typename T >
    inline T read()
    {
    	T x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * w; 
    }
    
    ll gcd(ll n, ll m) { return m ? gcd(m, n % m) : n; }
    
    void getst()
    {
    	for(int i = 1; i <= 17; i++)
    		for(int j = 1; j + (1 << i) - 1 <= n; j++)
    			st[i][j] = gcd(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]); 
    }
    
    ll query(int l, int r)
    {
    	int x = lg[r - l + 1]; 
    	return gcd(st[x][l], st[x][r - (1 << x) + 1]); 
    }
    
    int main()
    {
    	n = read <int> ();
    	for(int i = 2; i <= n; i++) lg[i] = lg[i >> 1] + 1; 
    	for(int i = 1; i <= n; i++)
    		st[0][i] = read <ll> ();
    	getst();
    	for(int l, r, mid, i = 1; i <= n; i++)
    		for(int res, j = i; j <= n; j = res + 1)
    		{
    			l = j, r = n;
    			while(l <= r)
    			{
    				mid = (l + r) >> 1;
    				if(query(i, j) == query(i, mid)) res = mid, l = mid + 1;
    				else r = mid - 1; 
    			}
    			ans = max(ans, 1ll * (res - i + 1) * query(i, res)); 
    		}
    	printf("%lld
    ", ans); 
    	return 0; 
    }
    
  • 相关阅读:
    Js/Jquery获取iframe中的元素
    js常用技巧汇总
    jquery常用技巧
    Tomcat远程调试
    常用SQL
    CRM-stark组件
    面试题-linux基础
    vue2-通过axios实现数据请求
    Vue01
    面试题之python基础
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12358813.html
Copyright © 2011-2022 走看看