wannalfy 挑战赛7 E 珂朵莉与GCD (离线+线段树/树状数组)

链接:https://www.nowcoder.com/acm/contest/56/E

时间限制:C/C++ 5秒,其他语言10秒

空间限制:C/C++ 716800K,其他语言1433600K
64bit IO Format: %lld

题目描述

给你一个长为n的序列a

m次查询

每次查询一个区间的所有子区间的gcd的和mod1e9+7的结果

输入描述:

第一行两个数n,m
之后一行n个数表示a
之后m行每行两个数l,r表示查询的区间

输出描述:

对于每个询问,输出一行一个数表示答案
示例1

输入

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 }

 

posted on 2018-02-19 16:59  scau_bi  阅读(323)  评论(0编辑  收藏  举报

导航