CCF/CSP-201709-5-除法

问题描述
  小葱喜欢除法,所以他给了你N个数a1a2, ⋯, aN,并且希望你执行M次操作,每次操作可能有以下两种:
  给你三个数lrv,你需要将alal+1, ⋯, ar之间所有v的倍数除以v
  给你两个数lr,你需要回答al + al+1 + ⋯ + ar的值是多少。
输入格式
  第一行两个整数NM,代表数的个数和操作的次数。
  接下来一行N个整数,代表N个数一开始的值。
  接下来M行,每行代表依次操作。每行开始有一个整数opt。如果opt=1,那么接下来有三个数lrv,代表这次操作需要将第l个数到第r个数中v的倍数除以v;如果opt = 2,那么接下来有两个数lr,代表你需要回答第l个数到第r个数的和。
输出格式
  对于每一次的第二种操作,输出一行代表这次操作所询问的值。
样例输入
5 3
1 2 3 4 5
2 1 5
1 1 3 2
2 1 5
样例输出
15
14
评测用例规模与约定
  对于30%的评测用例,1 ≤ NM ≤ 1000;
  对于另外20%的评测用例,第一种操作中一定有l = r
  对于另外20%的评测用例,第一种操作中一定有l = 1 , r = N
  对于100%的评测用例,1 ≤ NM ≤ 105,0 ≤ a1a2, ⋯, aN ≤ 106, 1 ≤ ≤ 106, 1 ≤ l ≤ r ≤ N
 
 
暴力可以拿到50分,BIT还是50,,,然后用网上的奇怪的优化后才100.
感觉这种写法貌似有点假,可能不是完全的正解。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pii pair<int,int>
 4 #define mp make_pair
 5 const int maxn=100005;
 6 int N,M;
 7 int a[maxn];
 8 long long c[maxn];
 9 int lowbit(int x){return x&-x;}
10 void update(int i,int k){
11     while(i<=N){
12         c[i]+=k;
13         i+=lowbit(i);
14     }
15 }
16 long long sum(int i){
17     long long r=0;
18     while(i){
19         r+=c[i];
20         i-=lowbit(i);
21     }
22     return r;
23 }
24 
25 int main(){
26     int op,l,r,v;
27     scanf("%d%d",&N,&M);
28     for(int i=1;i<=N;++i)scanf("%d",&a[i]),update(i,a[i]);
29     while(M--){
30         scanf("%d",&op);
31         if(op==1){
32             scanf("%d%d%d",&l,&r,&v);
33             if(v==1)continue;
34             while(l<=r){
35                 if(a[l]>=v&&a[l]%v==0) update(l,a[l]/v-a[l]),a[l]/=v;
36                 l++;
37             }
38         }else{
39             scanf("%d%d",&l,&r);
40             printf("%lld
",sum(r)-sum(l-1));
41         }
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/zzqc/p/12442826.html