长沙理工校赛I题题解-连续区间的最大公约数
题目来源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题题解-连续区间的最大公约数的更多相关文章
- 牛客-长沙理工校赛C-取手机
传送门:https://www.nowcoder.com/acm/contest/96/C 参考:http://www.cnblogs.com/Dillonh/p/8835074.html 题意: d ...
- 2019年华南理工校赛(春季赛)--I--炒股(简单思维水题)
水题,想想就过了 题目如下: 链接:https://ac.nowcoder.com/acm/contest/625/I来源:牛客网 攒机一时爽,一直攒机一直爽. 沉迷攒机的胡老师很快就发现,他每天只能 ...
- 2019字节跳动冬令营day7娱乐赛19题题解
啊没去听讲题,也没发纸质题解,电子版题解也没有 为最后几个unsolve自闭了一段时间才全都A掉 3个队友写的我没看的题通过人数蛮多就不管了 题目地址:https://pan.baidu.com/s/ ...
- csp-s模拟测试55 联,赛,题题解
题面:https://www.cnblogs.com/Juve/articles/11610969.html 联: 用线段树维护区间和,要修改成1或0就线段树修改区间和 如果是异或,那么新的区间和就是 ...
- 2019山东ACM省赛L题题解(FLOYD传递闭包的变形)
本题地址 https://cn.vjudge.net/contest/302014#problem/L Median Time Limit: 1 Second Memory Limit: 6 ...
- 18华南理工校赛 K 小马哥的超级盐水
https://www.nowcoder.com/acm/contest/94/K sum(ai)/sum(bi) = x/y <=> sum(ai*yi-bi*x) = 0 跟这题有点类 ...
- 福建工程学院第十四届ACM校赛M题题解 fwt进阶,手推三进制fwt
第九集,结束亦是开始 题意: 大致意思就是给你n个3进制的数字,让你计算有多少对数字的哈夫曼距离等于i(0<=i<=2^m) 思路: 这个是一个防ak题,做法是要手推公式的fwt 大概就这 ...
- 福建工程学院第十四届ACM校赛G题题解
外传:编剧说了不玩游戏不行 题意: 有n个石堆,我每次只能从某一堆中取偶数个石子,你取奇数个,我先手,先不能操作的人输.问最后谁能赢. 思路: 这个题仔细想想,就发现,取奇数的人有巨大的优势,因为假设 ...
- 福建工程学院第十四届ACM校赛B题题解
第二集,未来的我发量这么捉急的吗 题意: 有n个数,请问有多少对数字(i,j)(1<=i<j<=n),满足(a[i]^a[j])+((a[i]&a[j])<<1) ...
随机推荐
- 6- vue django restful framework 打造生鲜超市 -完成商品列表页(下)
Vue+Django REST framework实战 搭建一个前后端分离的生鲜超市网站 Django rtf 完成 商品列表页下 drf中的request和response drf对于django的 ...
- Linux监控一之Nagios的安装与配置
一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等.在系统或服务状态异常时发出邮件或短信报 ...
- jupyter notebook(一)——anaconda安装后jupyter不能自动跳转网页
1.问题描述 之前没有遇到过.这次重装系统,发现安装anaconda这个集成版python后,jupyter notebook打开后不能自动跳转打开的交互网页. 系统是windows7.anacond ...
- 科学计算库Numpy——运算
np.multiply(array1,array2) 该函数用于数组中对应位置上的数相乘. 一维向量 二维数组 np.dot(array1,array2) 两个数组都是一维向量 数组中对应位置上的数相 ...
- 三次样条插值matlab实现
三次样条插值matlab实现 %三次样条差值-matlab通用程序 - zhangxiaolu2015的专栏 - CSDN博客 https://blog.csdn.net/zhangxiaolu201 ...
- 洛谷 P2205 [USACO13JAN]画栅栏
这题其实没什么,但用到的算法都十分有用.做一个不恰当的比喻,这是一只必须用牛刀杀的鸡,但因为我这个蒟蒻杀不死牛,所以只能找只鸡来练练手. 题目描述 Farmer John 想出了一个给牛棚旁的长围墙涂 ...
- 手机注册过哪些网站37kfenxi.com,查询注册过哪些网站
注册过哪些网站?发现这么一个网站,https://www.37kfenxi.com?_=cnblogs 可以根据手机号码查询注册过哪些网站,然后通过大数据分析出机主的性格,爱好等. 据说还可以查老板, ...
- Diycode开源项目 Glide图片加载分析
1.使用Glide前的准备 1.1.首先要build.gradle中添加 github原地址点击我. 参考博客:Glide-开始! 参考博客:android图片加载库Glide的使用介绍. 参考博 ...
- Set-DnsServerGlobalQueryBlockList
Set-DnsServerGlobalQueryBlockList Windows Server Technical Preview and Windows 10 Other Versions ...
- 使用 Sconfig.cmd 配置服务器核心服务器
使用 Sconfig.cmd 配置服务器核心服务器 适用对象:Windows Server 2012 R2, Windows Server 2012 在 Windows Server 2012 中,你 ...