Problem Description
Rikka and Yuta are interested in Phi function (which is known as Euler's totient function).
Yuta gives Rikka an array A[1..n] of positive integers, then Yuta makes m queries.
There are three types of queries:
1lr
Change A[i] into φ(A[i]), for all i∈[l,r].
2lrx
Change A[i] into x, for all i∈[l,r].
3lr
Sum up A[i], for all i∈[l,r].
Help Rikka by computing the results of queries of type 3.
Yuta gives Rikka an array A[1..n] of positive integers, then Yuta makes m queries.
There are three types of queries:
1lr
Change A[i] into φ(A[i]), for all i∈[l,r].
2lrx
Change A[i] into x, for all i∈[l,r].
3lr
Sum up A[i], for all i∈[l,r].
Help Rikka by computing the results of queries of type 3.
Input
The first line contains a number T(T≤100) ——The number of the testcases. And there are no more than 2 testcases with n>105
For each testcase, the first line contains two numbers n,m(n≤3×105,m≤3×105)。
The second line contains n numbers A[i]
Each of the next m lines contains the description of the query.
It is guaranteed that 1≤A[i]≤107 At any moment.
For each testcase, the first line contains two numbers n,m(n≤3×105,m≤3×105)。
The second line contains n numbers A[i]
Each of the next m lines contains the description of the query.
It is guaranteed that 1≤A[i]≤107 At any moment.
Output
For each query of type 3, print one number which represents the answer.
改段求段,用线段树解决,首先预处理好欧拉函数
#include <iostream> #include <cstring> #include <cstdio> typedef long long LL; using namespace std; const int N = 10000001; #define SIZE 300005 LL p[N]; // phi(N) LL a[SIZE],st[SIZE * 4 + 5],n,m; LL changed[SIZE * 4 + 5]; int T; LL Left(LL i){ return 2*i; } LL Right(LL i){ return 2*i+1; } void Build_Tree(LL i,LL l,LL r){ // cout << l << r << endl; changed[i] = 0; st[i] = 0; if (l == r){ LL v; scanf("%lld",&v); st[i] = v; changed[i] = v; } else { LL mid = l + (r-l) / 2; Build_Tree(Left(i),l,mid); Build_Tree(Right(i),mid+1,r); st[i] = st[Left(i)] + st[Right(i)]; } } void Push_Up(LL i){ st[i] = st[Left(i)] + st[Right(i)]; if (changed[Left(i)] == changed[Right(i)]) changed[i] =changed[Left(i)]; else changed[i] = 0; } void Push_Down(LL i,LL l,LL r){ if (changed[i]){ LL c = changed[i]; changed[Left(i)] = c; changed[Right(i)] = c; LL mid = l + (r-l) / 2; st[Left(i)] = (mid-l+1) * c; st[Right(i)] = (r-mid) * c; changed[i] = 0; } } void UpdateE(LL i,LL l,LL r,LL ql,LL qr){ if (changed[i] && ql <= l && qr >= r){ changed[i] = p[changed[i]]; st[i] = (r-l+1) * changed[i]; return; } LL mid = l + (r - l) / 2; if (l == r) return; Push_Down(i,l,r); if (ql <= mid) UpdateE(Left(i),l,mid,ql,qr); if (qr >= mid + 1) UpdateE(Right(i),mid+1,r,ql,qr); Push_Up(i); } void Update(LL i,LL l,LL r,LL ql,LL qr,LL c){ //ql、qr为需要更新的区间左右端点,addv为需要变更的值 if (ql <= l && qr >= r) { //与单点更新一样,当当前结点被需要更新的区间覆盖时 changed[i] = c; st[i] = (r-l+1) * c; return; } Push_Down(i,l,r); LL mid = l + (r-l) / 2; if (ql <= mid) Update(Left(i),l,mid,ql,qr,c); if (qr >= mid + 1) Update(Right(i),mid+1,r,ql,qr,c); Push_Up(i); } LL Query(LL i,LL l,LL r,LL ql,LL qr){ // 含义同上 if (ql <= l && qr >= r) return st[i]; Push_Down(i,l,r); LL mid = l + (r-l) / 2,ans = 0; if (ql <= mid) ans += Query(Left(i),l,mid,ql,qr); if (qr >= mid + 1) ans += Query(Right(i),mid+1,r,ql,qr); return ans; } void phi() { for(int i=1; i<N; i++) p[i] = i; for(int i=2; i<N; i+=2) p[i] >>= 1; for(int i=3; i<N; i+=2) { if(p[i] == i) { for(int j=i; j<N; j+=i) p[j] = p[j] - p[j] / i; } } } int main(){ // freopen("test.in","r",stdin); // ios::sync_with_stdio(false); phi(); scanf("%d",&T); for (int times = 1; times <= T; times ++){ scanf("%lld %lld",&n,&m); Build_Tree(1,1,n); for (int i=1;i<=m;i++){ int l,r,order; scanf("%d %d %d",&order,&l,&r); LL X; switch (order) { case 1: UpdateE(1,1,n,l,r); // for (int j=1;j<=25;j++){ // cout << st[j] << " "; // } // cout << endl; break; case 2: scanf("%lld",&X); Update(1,1,n,l,r,X); break; case 3: printf("%lld ",Query(1,1,n,l,r)); break; } } } return 0; }