数学题

题目背景
你喜欢数学吗!(反正我不喜欢)
不管你喜不喜欢!这是一道数学题!
题目描述
定义一个函数d(x)为x的约数个数。例如,d(4) = 3,d(12) = 6。
有n个数a1,a2,...,an,对它们进行两种操作:
1 l r:对所有i∈[l,r],将ai变成d(ai)。
2 l r:输出[l,r]的区间和。
输入输出格式
输入格式
第一行两个整数n和m,分别表示序列a的长度和操作次数。
第二行n个整数,表示序列a的初值。
接下来m行每行三个整数表示操作,格式见“题目描述”。
输出格式
对于每个操作2,输出一行答案。

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <map>
  7 #define space putchar(' ')
  8 #define enter putchar('
')
  9 typedef long long ll;
 10 using namespace std;
 11 template <class T>
 12 void read(T &x){    //读入优化啊 
 13     char c;
 14     bool op = 0;
 15     while(c = getchar(), c < '0' || c > '9')
 16         if(c == '-') op = 1;
 17     x = c - '0';
 18     while(c = getchar(), c >= '0' && c <= '9')
 19         x = x * 10 + c - '0';
 20     if(op) x = -x;
 21 }
 22 template <class T>
 23 void write(T x){    //又写读入优化又写输出优化的奆佬学姐 
 24     if(x < 0) putchar('-'), x = -x;
 25     if(x >= 10) write(x / 10);
 26     putchar('0' + x % 10);
 27 }
 28 
 29 const int N = 1e6 + 6, M = 3e5 + 6;
 30 int n, m;
 31 int prime[N], d[N], t[N];  
 32 bool p[N];  
 33 void init(int n){  
 34     d[1]=1; t[1]=0;  
 35     for (int i=2;i<=n;++i){  
 36         if(!p[i]) prime[++prime[0]]=i, d[i]=2, t[i]=1;  
 37         for (int j=1;j<=prime[0] && i*prime[j] <= n;++j){  
 38             p[i*prime[j]]=1;  
 39             if (!(i%prime[j])){
 40                 d[i*prime[j]]=d[i]/(t[i]+1)*(t[i]+2);
 41                 t[i*prime[j]]=t[i]+1;
 42                 break;
 43             }  
 44             else{
 45                 d[i*prime[j]]=d[i]*2;
 46                 t[i*prime[j]]=1;
 47             }  
 48         }   
 49     }
 50 }
 51 ll data[4 * M];
 52 int mx[4 * M], a[M];
 53 bool done[4 * M];
 54 
 55 void build(int k, int l, int r){    //种树 
 56     if(l == r){
 57         data[k] = mx[k] = a[l];
 58         if(mx[k] <= 2) done[k] = 1;
 59         return;
 60     }
 61     int mid = (l + r) >> 1;
 62     build(k << 1, l, mid);
 63     build(k << 1 | 1, mid + 1, r);
 64     data[k] = data[k << 1] + data[k << 1 | 1];
 65     mx[k] = max(mx[k << 1], mx[k << 1 | 1]);
 66     if(mx[k] <= 2) done[k] = 1;
 67 }
 68 void change(int k, int l, int r, int ql, int qr){    //这就是那个求约数个数的骚操作 
 69     if(l == r){
 70         data[k] = mx[k] = d[data[k]];
 71         if(mx[k] <= 2) done[k] = 1;
 72         return;
 73     }
 74     int mid = (l + r) >> 1;
 75     if(ql <= mid && !done[k << 1]) change(k << 1, l, mid, ql, qr);
 76     if(qr > mid && !done[k << 1 | 1]) change(k << 1 | 1, mid + 1, r, ql, qr);
 77     data[k] = data[k << 1] + data[k << 1 | 1];
 78     mx[k] = max(mx[k << 1], mx[k << 1 | 1]);
 79     if(mx[k] <= 2) done[k] = 1;
 80 }
 81 ll query(int k, int l, int r, int ql, int qr){    //这是求和 
 82     if(ql <= l && qr >= r) return data[k];
 83     int mid = (l + r) >> 1;
 84     ll ret = 0;
 85     if(ql <= mid) ret += query(k << 1, l, mid, ql, qr);
 86     if(qr > mid) ret += query(k << 1 | 1, mid + 1, r, ql, qr);
 87     return ret;
 88 }
 89 
 90 int main(){
 91 freopen("math.in","r",stdin);freopen("math.out","w",stdout);
 92     init(1e6 + 3);
 93     read(n), read(m);
 94     for(int i = 1; i <= n; i++) read(a[i]);
 95     build(1, 1, n);
 96     int op, l, r;
 97     while(m--){
 98         read(op), read(l), read(r);
 99         if(op == 1) change(1, 1, n, l, r);
100         else write(query(1, 1, n, l, r)), enter;
101     }
102         
103     return 0;
104 }

这题我懒得改

而且也不会改

所以只xjb写了几句注释

我也不是像ypq那样脑洞巨大的人是吧(

原文地址:https://www.cnblogs.com/aristocrat/p/8466090.html