The following:
Define a Niconico-number, if X is Niconico-number, then all integers less than x and x coprime are a arithmetic progression, initially giving an array of n numbers, three operations:
1 L r Q How many niconico-number numbers are there in [L,r]
2 L R v for all numbers in [l,r] to V
3 k x Changes the number of K to X
Make output for each enquiry. Parse (Turn):
1, first write a find the law of the program, found that there are three kinds of niconico-number is the first is prime, the second is 2 of the X power, the third is 6
2, can build a table, directly labeled a number is not niconico-number
3, the use of line-tree maintenance interval of the number of Niconico-number, and then you can make a number of changes, and a range of inquiries.
The key for the second operation. We need to know that for a number of X-min operations, a maximum of log (x) is performed, because at least one reduction in the value of each is reduced by half, so there will be a maximum of log (x) operations for each number, which will be followed by a V greater than the current value.
Since the number of times is not much, then the region can be used to violence, maintain a section of the maximum value, if the maximum value is less than V, then this section does not need to update, otherwise the lowest layer of the traversal to take the remainder.
4, for the number of N, to find a number requires log (n), a number will be modified log (x) times, so the total time will not exceed N∗log (n) ∗log (x) n*log (n) *log (x).
My My Code code
#pragma COMMENT (linker, "/stack:102400000,102400000") #include <cstdio> #include <cstring> #include < algorithm> #define LS (o<<1) #define RS (o<<1|1) #define Lson ls, L, M #define Rson rs, m+1, R using NAMESP
Ace STD;
const int MAXX = (int) 1e7 + 5;
const int MAXN = (int) 1e5 + 5;
BOOL Nico[maxx*2];
int A[MAXN];
int n, q;
void Prepare () {memset (Nico, True, sizeof (Nico));
for (int i = 2; i < MAXX i++) {if (!nico[i)) continue;
Nico[i] = true;
for (int j = I*2 J < MAXX J + = i) {Nico[j] = false;
}} Nico[6] = true;
for (int i = 1; i < MAXX i <<= 1) {nico[i] = true;
int MAXV[MAXN << 2], SUMV[MAXN << 2];
void pushup (int o) {Maxv[o] = max (Maxv[ls], maxv[rs]);
Sumv[o] = Sumv[ls] + sumv[rs];
} void Build (int o, int L, int R) {if (L = = r) {Maxv[o] = a[l];
Sumv[o] = nico[a[l]];
return;
int M = (L + R)/2;Build (Lson);
Build (Rson);
Pushup (o);
int query (int o, int L, int R, int ql, int qr) {if (QL <= L && R <= qr) return sumv[o];
int M = (L + R)/2, ret = 0;
if (QL <= M) ret + query (Lson, QL, QR);
if (QR > M) ret + query (Rson, QL, QR);
return ret;
} void SetValue (int o, int L, int R, int pos, int val) {if (L = = R) {Sumv[o] = Nico[val];
Maxv[o] = val;
return;
int M = (L + R)/2;
if (POS <= M) setValue (Lson, POS, Val);
else SetValue (Rson, POS, Val);
Pushup (o); } void Modify (int o, int L, int R, int ql, int qr, int val) {if (QL <= L && R <= qr && val >
Maxv[o]) return;
if (L = = = R) {Maxv[o]%= val;
Sumv[o] = Nico[maxv[o]];
return;
int M = (L + R)/2;
if (QL <= M) Modify (Lson, QL, QR, Val);
if (QR > M) Modify (Rson, QL, QR, Val);
Pushup (o);
int main () {prepare (); while (scanf ("%d"),&n!= EOF) {for (int i = 1; I <= n; i++) {scanf ("%d", &a[i]);
Build (1, 1, N);
scanf ("%d", &q);
int oper, QL, QR, Val;
while (q--) {scanf ("%d", &oper);
if (oper = = 1) {scanf ("%d%d", &QL, &QR);
printf ("%d\n", Query (1, 1, N, QL, QR));
}else if (oper = = 2) {scanf ("%d%d%d", &QL, &QR, &val);
Modify (1, 1, N, QL, QR, Val);
}else {scanf ("%d%d", &QL, &val);
SetValue (1, 1, N, QL, Val);
}} return 0; }