题目来源https://www.nowcoder.com/acm/contest/96/I

解题前们需要先知道几个结论:

首先,gcd是有区单调性的: gcd(L,R)>=gcd(L,R+d)  ,因为每添加一个数,gcd只会变小或者不变。

其次,以L左端点的所有区间的【GCD的种类数】一般不超过15,最多不超过31个,因为gcd每次变小时会除掉当前gcd的一个或多个质因子,所以质因数的个数,决定这个gcd

最多能变小几次,而质因子最多的数就是2^31。

预处理:

在解决问题之前我们先做几个预处理,至于这些预处理有什么用,在解题时会说明。

  • :为了快速查询区间gcd我们需要,用ST表先预处理一下数组,使得我们查询任意区间gcd的复杂下降至只需一个gcd(),即O(log(x)).   因为算gcd要一个log的复杂所以总复杂度,近似为 nlog(n)^2
  • 对于每个L,二分计算区间内每种gcd的起始右端点,比如区间[8,4,4,2] 的区间,以下标1开始的区间gcd有 8,4,2这3种gcd,对应的右端点分别为[1,2,4]。因为计算gcd要一个log,二分一个log,而gcd种类数是期望好像是只比O(n)稍大(我瞎猜,不会证【1】)。所以总复杂度是接近nlog(n)^2

计算:设gcd[L,R]=g,要计算有多少个子区间为,其实就算算对于每个Li,对应Ri至少要多少才能使得gcd[Li,Ri]=g。 而答案为Σ(R+1-Ri)

如果你对每个LI都计算R的话,再快也是O(区间长度的) ,没前途。这有个更优美的求法,其实对于任意的Li和g,对应的Ri我们都在预处理的时候算好了,

但是按Li查询的复杂度太高了,那么为啥不考虑一下按g查询

所以在预处理阶段,我们按g分组,并在每个组内并按Li排序(其实按Ri还是按Li都是一样的,因为组内有类似尺取的区间单调性,这点自己手动模拟一下就知道了),

并预处理Ri的前缀和。  接着查询L,R时,在g的组内二分(如果数据是随机的话,暴力也是行的)一下,L<=Li&&Ri<=R 的 区间,利用RI的前缀和一减就可以得分Σ(R+1-Ri)

将映射g到组id,用hash,可O(1).  平均组长log(n).,最坏组长O(n)  .   查询复杂度是 平均时log(log(n))  最快log(n)

加上预处理,最坏复杂度近似为 O(qlogn+nlog(n)^2)

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
using namespace std;
typedef long long ll;
#define N 280000
int dp[][];
int len[];
int a[];
struct node
{
int l,r;
long long sum;
} p;
vector<node>e[];
map<int,int>mp;
inline int cal(int l,int r)
{
if(l>r)
return -;
int k=len[r-l+];
return __gcd(dp[l][k],dp[r-(<<k)+][k]);
}
inline int findr(int l,int r,int g)
{
int k=len[r-l+],b=l,i;
for(i=<<k; i; i>>=)
{
if(b+i<=r&&cal(l,b+i)>=g)
{
b+=i;
}
}
return b;
}
inline int findl(int l,int r,int g)
{
int k=len[r-l+],b=r,i;
for(i=<<k; i; i>>=)
{
if(b-i>=l&&cal(l,b-i)<=g)
{
b-=i;
}
}
return b;
}
int fl(int g,int x)
{
int l=,r,m,k;
k=mp[g];
r=e[k].size();
while(l+<r)
{
m=(l+r)/;
if(e[k][m].l<x)
{
l=m;
}
else
{
r=m;
}
}
return l;
}
int fr(int g,int x)
{
int l=,r,m,k;
k=mp[g];
r=e[k].size();
while(l+<r)
{
m=(l+r)/;
if(e[k][m].r<=x)
{
l=m;
}
else
{
r=m;
}
}
return l;
}
long long fun(int l,int r,int g)
{
long long ans=;
long long a,b;
a=fl(g,l);;
b=fr(g,r);
int k=mp[g];
ans=(b-a)*(r+)-(e[k][b].sum-e[k][a].sum);
return ans;
}
int main()
{
int n,m,k,l,r,i,j,g,q,t,cas=;
len[]=;
for(i=; i<=; i++)
{
len[i]=len[i/]+;
}
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(dp,,sizeof(dp));
mp.clear();
for(i=; i<=n; i++)
{
scanf("%d",&a[i]);
dp[i][]=a[i];
}
for(j=; j<=len[n]; j++)
{
for(i=; i<=n; i++)
{
dp[i][j]=__gcd(dp[i][j-],dp[i+(<<j-)][j-]);
}
}
int ll;
for(i=; i<=n; i++)
{
g=a[i];
ll=i;
while()
{
if(mp.count(g)==)
{
mp[g]=mp.size();
p.l=;
p.r=;
p.sum=;
e[mp[g]].push_back(p);
}
p.l=i;
ll=findr(i,n,g);
p.r=findl(i,n,g);
e[mp[g]].push_back(p);
if(ll>=n)
break;
g=__gcd(g,a[ll+]);
}
}
for(i=; i<=mp.size(); i++)
{
for(j=; j<e[i].size(); j++)
{
e[i][j].sum=e[i][j-].sum+e[i][j].r;
} }
scanf("%d",&q);
printf("Case #%d:\n",cas++);
while(q--)
{
scanf("%d%d",&l,&r);
g=cal(l,r);
printf("%d %lld\n",g,fun(l,r,g));
} for(i=; i<mp.size(); i++)
{
e[i].clear();
}
}
return ;
}

AC代码

长沙理工校赛I题题解-连续区间的最大公约数的更多相关文章

  1. 牛客-长沙理工校赛C-取手机

    传送门:https://www.nowcoder.com/acm/contest/96/C 参考:http://www.cnblogs.com/Dillonh/p/8835074.html 题意: d ...

  2. 2019年华南理工校赛(春季赛)--I--炒股(简单思维水题)

    水题,想想就过了 题目如下: 链接:https://ac.nowcoder.com/acm/contest/625/I来源:牛客网 攒机一时爽,一直攒机一直爽. 沉迷攒机的胡老师很快就发现,他每天只能 ...

  3. 2019字节跳动冬令营day7娱乐赛19题题解

    啊没去听讲题,也没发纸质题解,电子版题解也没有 为最后几个unsolve自闭了一段时间才全都A掉 3个队友写的我没看的题通过人数蛮多就不管了 题目地址:https://pan.baidu.com/s/ ...

  4. csp-s模拟测试55 联,赛,题题解

    题面:https://www.cnblogs.com/Juve/articles/11610969.html 联: 用线段树维护区间和,要修改成1或0就线段树修改区间和 如果是异或,那么新的区间和就是 ...

  5. 2019山东ACM省赛L题题解(FLOYD传递闭包的变形)

    本题地址 https://cn.vjudge.net/contest/302014#problem/L Median Time Limit: 1 Second      Memory Limit: 6 ...

  6. 18华南理工校赛 K 小马哥的超级盐水

    https://www.nowcoder.com/acm/contest/94/K sum(ai)/sum(bi) = x/y <=> sum(ai*yi-bi*x) = 0 跟这题有点类 ...

  7. 福建工程学院第十四届ACM校赛M题题解 fwt进阶,手推三进制fwt

    第九集,结束亦是开始 题意: 大致意思就是给你n个3进制的数字,让你计算有多少对数字的哈夫曼距离等于i(0<=i<=2^m) 思路: 这个是一个防ak题,做法是要手推公式的fwt 大概就这 ...

  8. 福建工程学院第十四届ACM校赛G题题解

    外传:编剧说了不玩游戏不行 题意: 有n个石堆,我每次只能从某一堆中取偶数个石子,你取奇数个,我先手,先不能操作的人输.问最后谁能赢. 思路: 这个题仔细想想,就发现,取奇数的人有巨大的优势,因为假设 ...

  9. 福建工程学院第十四届ACM校赛B题题解

    第二集,未来的我发量这么捉急的吗 题意: 有n个数,请问有多少对数字(i,j)(1<=i<j<=n),满足(a[i]^a[j])+((a[i]&a[j])<<1) ...

随机推荐

  1. 项目十八-Hadoop+Hbase分布式集群架构“完全篇”

    本文收录在Linux运维企业架构实战系列 前言:本篇博客是博主踩过无数坑,反复查阅资料,一步步搭建,操作完成后整理的个人心得,分享给大家~~~ 1.认识Hadoop和Hbase 1.1 hadoop简 ...

  2. 两台centos之间使用scp命令传输文件

    1.将本地文件copy到远程 (1)复制文件 scp local_file remote_username@remote_ip:remote_folder 例如:将/usr/local/aa.png文 ...

  3. ES6箭头函数基本用法

    ES6箭头函数基本用法 ``` window.onload = function(){ alert(abc); } //箭头函数 window.onload = ()=>{ alert(&quo ...

  4. tcl之list操作-lappend/lsearch/lsort/concat/split/join/

  5. CodeForces 651B

    #include <cstdio> #include <algorithm> using namespace std; int a[1005], n, temp, maxk; ...

  6. A1016 Phone Bills (25)(25 分)

    A1016 Phone Bills (25)(25 分) A long-distance telephone company charges its customers by the followin ...

  7. 笔记-编程-IO模型

    笔记-编程-IO模型 1.      简介 常用IO模型 1)      同步阻塞IO(Blocking IO) 2)      同步非阻塞IO(Non-blocking IO) 3)      IO ...

  8. python 闯关之路四(下)(并发编程与数据库编程) 并发编程重点

    python 闯关之路四(下)(并发编程与数据库编程)   并发编程重点: 1 2 3 4 5 6 7 并发编程:线程.进程.队列.IO多路模型   操作系统工作原理介绍.线程.进程演化史.特点.区别 ...

  9. P3386 【模板】二分图匹配(匈牙利&最大流)

    P3386 [模板]二分图匹配 题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正 ...

  10. [oldboy-django][2深入django]登录注册页面验证码

    后台生成随机验证码 #验证码生成 - 在login.html 中有一张验证码图片 设置图片的src url, 相当于发送一次get请求,返回的内容为图片渲染的内容 <div class=&quo ...