题目来源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. php 获取 今天、昨天、这周、上周、这月、上月、近30天

    <?php //今天 $today = date("Y-m-d"); //昨天 $yesterday = date("Y-m-d", strtotime( ...

  2. PHP判断时关于null,0,true,flase的值

    <?php// $wh = 0; //等于整数0,等于字符串'0',等于空字符串,等于空格字符串, 等于空(null),等于字符串('null')// $wh = '0'; //=>等于整 ...

  3. 数据存储之使用mysql数据库存储数据

    推荐安装mysql5.7环境: 官网下载:https://dev.mysql.com/downloads/installer/5.7.html 如果提示没有.NET Framework框架.那么就在提 ...

  4. 第15课 栏目的排序处理(组件化) Thinkphp5商城第四季

    目录 要实现的功能 思路: 视图层 控制器里: 扩展函数里 要实现的功能 用表单里的提交过来的sort数据,批量修改表里的排序值 界面效果: 思路: 视图层表单提交数据主键=>sort值 控制器 ...

  5. Django2.2使用mysql数据库pymysql版本不匹配问题的解决过程与总结

    前置条件 django版本:2.2.1 python版本:3.6.6 mysql版本:mysql-community8.0.15 问题 在搭建django项目,配置mysql数据库时遇到无法迁移数据库 ...

  6. Python入门基础--变量与基本数据类型

    变量 什么是变量 变量就是变化的量,变就是变化,量用于衡量描述对象的状态 为什么要有变量 程序执行的本质就是一系列状态的变化,变是程序执行的直接体现,所以我们需要有一种机制能够反映或者说是保存下来程序 ...

  7. momo不是玩具,.Net雄起

    互联网时代 .NET 会渐渐衰落吗?一个架构师对 .NET 的思考 2015-12-14 11:03 darklx 博客园 字号:T | T 为了更好的适应互联网时代的需求,我们公司已经把我们的 .N ...

  8. (Winform)控件中添加GIF图片以及运用双缓冲使其不闪烁以及背景是gif时使控件(如panel)变透明

    Image img = Image.FromFile(@"C:\Users\joeymary\Desktop\3.gif"); pictureBox1.Image =img.Clo ...

  9. Spring---环境搭建与包介绍

    jar包下载路径 首先需要下载Spring框架 spring-framework-5.0.0.RELEASE-dist,官方地址为https://repo.spring.io/release/org/ ...

  10. 计算时间复杂度&空间复杂度

    1.下面函数的复杂度是: long foo(long x){ if(x<2) return 1; return x*x*foo(x-1); } 解析: 当n>=2时 foo(n)=n^2* ...