wannalfy 挑战赛7 E 珂朵莉与GCD (离线+线段树/树状数组)
链接:https://www.nowcoder.com/acm/contest/56/E
时间限制:C/C++ 5秒,其他语言10秒
64bit IO Format: %lld
题目描述
给你一个长为n的序列a
m次查询
每次查询一个区间的所有子区间的gcd的和mod1e9+7的结果
输入描述:
第一行两个数n,m
之后一行n个数表示a
之后m行每行两个数l,r表示查询的区间
输出描述:
对于每个询问,输出一行一个数表示答案
输入
5 7 30 60 20 20 20 1 1 1 5 2 4 3 4 3 5 2 5 2 3
输出
30 330 160 60 120 240 100
说明
[1,1]的子区间只有[1,1],其gcd为30
[1,5]的子区间有:
[1,1]=30,[1,2]=30,[1,3]=10,[1,4]=10,[1,5]=10
[2,2]=60,[2,3]=20,[2,4]=20,[2,5]=20
[3,3]=20,[3,4]=20,[3,5]=20
[4,4]=20,[4,5]=20
[5,5]=20
总共330
[2,4]的子区间有:
[2,2]=60,[2,3]=20,[2,4]=20
[3,3]=20,[3,4]=20
[4,4]=20
总共160
[3,4]的子区间有:
[3,3]=20,[3,4]=20
[4,4]=20
总共60
[3,5]的子区间有:
[3,3]=20,[3,4]=20,[3,5]=20
[4,4]=20,[4,5]=20
[5,5]=20
总共120
[2,5]的子区间有:
[2,2]=60,[2,3]=20,[2,4]=20,[2,5]=20
[3,3]=20,[3,4]=20,[3,5]=20
[4,4]=20,[4,5]=20
[5,5]=20
总共240
[2,3]的子区间有:
[2,2]=60,[2,3]=20
[3,3]=20
总共100
备注:
对于100%的数据,有1 <= n , m , ai <= 100000
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
根据一个数的唯一分解,一个r往左边的gcd最多个分成个区间,相同区间内的点到r的gcd是一样的
对于询问(l , r) ,枚举子区间的右端点从l到r,如果子区间右端点为 l到r-1 都处理好了就只需要坐享前面更新的成果,然后更新r为右端点的区间就好了
把询问离线,,因此需要区间更新和区间求和,线段树的就不写了
新学树状数组的区间更新和区间求和,用差分的思想
贴了别人的blog,我也是看了别人的(侵删)http://blog.csdn.net/fsahfgsadhsakndas/article/details/52650026
1 #include <bits/stdc++.h> 2 #define mst(a,b) memset((a),(b), sizeof a) 3 #define lowbit(a) ((a)&(-a)) 4 #define IOS ios::sync_with_stdio(0);cin.tie(0); 5 #define MP make_pair 6 using namespace std; 7 typedef long long ll; 8 typedef pair<int,int> pii; 9 const int mod=1e9+7; 10 const int maxn=1e5+10; 11 int n,m; 12 int a[maxn],nx[maxn]; 13 int ans[maxn]; 14 vector<pii>uu[maxn]; 15 int c1[maxn],c2[maxn]; 16 void update(int *bits,int pos,int val){ 17 for(;pos<=n;pos+=lowbit(pos)) 18 bits[pos]=(bits[pos]+val)%mod; 19 } 20 int get(int *bits,int pos){ 21 int ret=0; 22 for(;pos;pos-=lowbit(pos))ret=(ret+bits[pos])%mod; 23 return (ret+mod)%mod; 24 } 25 void add(int l,int r,int val){ 26 update(c1,l,val),update(c2,l,1LL*(l-1)*val%mod); 27 28 update(c1,r+1,-val),update(c2,r+1,-1LL*r*val%mod); 29 } 30 int query(int pos){ 31 return (1LL*pos*get(c1,pos)-get(c2,pos)+mod)%mod; 32 } 33 int query(int l,int r){ 34 return (query(r)-query(l-1)+mod)%mod; 35 } 36 int main(){ 37 #ifdef local 38 freopen("in.txt","r",stdin); 39 //freopen("out.txt","w",stdout); 40 #endif 41 scanf("%d%d",&n,&m); 42 for(int i=1;i<=n;++i)scanf("%d",&a[i]),nx[i]=i-1; 43 for(int i=1;i<=m;++i){ 44 int l,r;scanf("%d%d",&l,&r); 45 uu[r].push_back(MP(l,i)); 46 } 47 for(int i=1;i<=n;++i){ 48 for(int j=i;j;j=nx[j])a[j]=__gcd(a[j],a[i]); 49 50 for(int j=i;nx[j];j=nx[j]) 51 while(nx[j]&&a[j]==a[nx[j]])nx[j]=nx[nx[j]]; 52 53 for(int j=i;j;j=nx[j])add(nx[j]+1,j,a[j]); 54 55 for(int j=0;j<uu[i].size();++j){ 56 pii&k = uu[i][j]; 57 ans[k.second]=query(k.first,i); 58 } 59 } 60 for(int i=1;i<=m;++i)printf("%d\n",ans[i]); 61 return 0; 62 }