显示代码纯文本
#define MAXN 50010UL
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
int n, Q, pr[MAXN], u[MAXN];
ll c[MAXN];
bool vis[MAXN];
vector <int> V[MAXN];
void Pre(int r) {
u[1] = 1;
for(int i = 2 ; i <= r ; ++ i) {
if(!vis[i]) pr[++ pr[0]] = i, u[i] = -1;
for(int j = 1 ; j <= pr[0] && 1ll*i*pr[j] <= r ; ++ j) {
int nx = i*pr[j];
vis[nx] = true;
if(!(i%pr[j])) {
u[nx] = 0;
break;
} else u[nx] = -u[i];
}
}
for(int i = 1 ; i <= r ; ++ i) {
for(int j = i ; j <= r ; j += i) {
if((j/i)>=i) V[j].push_back(i);
if((j/i)>i) V[j].push_back(j/i);
}
}
return;
}
void Insert(int x, ll k) {
while(x<=n) {
c[x] += k;
x += x&(-x);
}
return;
}
ll Find(int x) {
ll ret = 0;
while(x>0) {
ret += c[x];
x -= x&(-x);
}
return ret;
}
void Add(int n, int d, int v) {
if((n%d)||v==0) return;
int len = V[n/d].size();
for(int i = 0 ; i < len ; ++ i) Insert(V[n/d][i]*d, 1ll*u[V[n/d][i]]*v);
return;
}
ll Ask(int x) {
ll ret = 0;
for(int i = 1, _last ; i <= x ; i = _last+1) {
_last = x/(x/i);
ret += 1ll*(x/i)*(Find(_last)-Find(i-1));
}
return ret;
}
int main() {
freopen("gcd_array.in", "r", stdin);
freopen("gcd_array.out", "w", stdout);
int op, x, y, z;
Pre(50000);
scanf("%d%d", &n, &Q);
for(int i = 1 ; i <= Q ; ++ i) {
scanf("%d", &op);
if(op==1) scanf("%d%d%d", &x, &y, &z), Add(x, y, z);
else scanf("%d", &x), printf("%lld\n", Ask(x));
}
return 0;
}