1. 程式人生 > >201709-5 除法 ccf

201709-5 除法 ccf

問題描述
  小蔥喜歡除法,所以他給了你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; }

這裡寫圖片描述