题目描述
给你一个 �(�≤100,000)N(N≤100,000) 个整数序列:�1,⋯,��(0<��≤1000,000,000)a1,⋯,an(0<ai≤1000,000,000)。 有 �(�≤100,000)Q(Q≤100,000) 个查询。 对于每个查询 �,�l,r,您必须计算 ���(��,,��+1,⋯,��)gcd(al,,al+1,⋯,ar) 并计算对的数量(�′,�′)(1≤�<�≤�)(l′,r′)(1≤l<r≤N),使得 ���(��′,��′+1,⋯,��′)gcd(al′,al′+1,⋯,ar′) 等于 ���(��,��+1,⋯,��)gcd(al,al+1,⋯,ar)。
输入描述
第一行输入包含一个数字�T,代表你需要解决的测试用例的数量。
每个 ����case 的第一行包含一个数字�(�≤100,000)N(N≤100,000),表示整数的数量。
第二行包含 �N 个整数,�1,⋯,��(0<��≤1000,000,000)a1,⋯,an(0<ai≤1000,000,000)。
第三行包含一个数字�(�≤100,000)Q(Q≤100,000),表示查询的数量。
对于接下来的 �Q 行,第 �i 行包含两个数字 ,代表 ��,��li,ri,代表第 �i 个查询。
输出描述
对于每个����case,需要在开头输出“Case #t:”。(不带引号,�t表示测试用例的编号,从11开始)。
对于每个查询,您需要在一行中输出两个数字。 第一个数字代表 ���(��,��+1,⋯,��)gcd(al,al+1,⋯,ar),第二个数字代表对 (�′,�′)(l′,r′) 的数量,使得 ���(��′,��′+1,⋯,��′)gcd(al′,al′+1,⋯,ar′) 等于 ���(��,��+1,⋯,��)gcd(al,al+1,⋯,ar)。
样例输入
151 2 4 6 741 52 43 44 4
样例输出
Case #1:1 82 42 46 1
代码
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
long long f[N][20],a[N],n,q,p[N],b[N],t;
map<int,long long>mp;
void build(){
for(int i=1;i<=n;i++ ) f[i][0]=a[i];
for(int j=1;(1<<j)<=n;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]);
}
}
}
int query(int L ,int R ){
int k=log2(R-L+1);
return __gcd(f[L][k],f[R-(1<<k)+1][k]);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
for(int cas=1;cas<=t;cas++){
mp.clear();
cout<<"Case #"<<cas<<":"<<"\n";
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>q;
build();
for(int i=1;i<=q;i++){
cin>>p[i]>>b[i];
int s=query(p[i],b[i]);
mp[s]=0;
}
for(int L=1;L<=n;L++){
int R=L;
while(R<=n){
int l=R,r=n,d1=query(L,R);
while(l<r){
int mid=l+r+1>>1;
if(query(L,mid)==d1) l=mid;
else r=mid-1;
}
if(mp.count(d1)) mp[d1]+=l-R+1;
R=l+1;
}
}
for(int i=1;i<=q;i++){
int s=query(p[i],b[i]);
cout<<s<<" "<<mp[s]<<"\n";
}
}
return 0;
}

被折叠的 条评论
为什么被折叠?



