201709-5 除法 ccf
阿新 • • 發佈:2018-12-31
問題描述
小蔥喜歡除法,所以他給了你N個數a1, a2, ⋯, aN,並且希望你執行M次操作,每次操作可能有以下兩種:
給你三個數l, r, v,你需要將al, al+1, ⋯, ar之間所有v的倍數除以v。
給你兩個數l, r,你需要回答al + al+1 + ⋯ + ar的值是多少。
輸入格式
第一行兩個整數N, M,代表數的個數和操作的次數。
接下來一行N個整數,代表N個數一開始的值。
輸出格式
對於每一次的第二種操作,輸出一行代表這次操作所詢問的值。
樣例輸入
5 3
1 2 3 4 5
2 1 5
1 1 3 2
2 1 5
樣例輸出
15
14
評測用例規模與約定
對於30%的評測用例,1 ≤ N, M ≤ 1000;
對於另外20%的評測用例,第一種操作中一定有l = r;
對於另外20%的評測用例,第一種操作中一定有l = 1 , r = N;
對於100%的評測用例,1 ≤ N, M ≤ 105,0 ≤ a1, a2, ⋯, aN ≤ 106, 1 ≤ v ≤ 106, 1 ≤ l ≤ r ≤ N。
#include <cstdio>
long long tree[101024];
int n,m,a[101024];
void update(int i,int val)
{
while(i<=n)
{
tree[i]+=val;
i+=-i&i;
}
}
long long getsum(int i)
{
long long sum=0;
while(i>0)
{
sum+=tree[i];
i-=-i&i;
}
return sum;
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
update(i,a[i]);
}
for(int i=1;i<=m;++i)
{
int opt,l,r,w;
scanf("%d %d %d",&opt,&l,&r);
if(opt==2) printf("%lld\n",getsum(r)-getsum(l-1));
else
{
scanf("%d",&w);
if(w==1)continue;
while(l<=r)
{
if(a[l]>=w&&a[l]%w==0)
{
update(l,-(a[l]-a[l]/w));
a[l]/=w;
}
++l;
}
}
}
return 0;
}