题解:因为一开始的序列是1,2,3,...... n。而修改次数m最大为1000.对于每次询问可以先假设没有改变任何位置上的数。然后把改变的地方存到map中再暴力修改。
对于原来的1~n个数,可以预处理出每个p的质因子,然后运用容斥定理求解与p不互质的个数,用总数减去即可。
#include"bits/stdc++.h"
using namespace std;
#define fi first
#define se second
typedef long long LL;
const int MX = 4e5+7;
int n,m;
bool no_prime[MX];
int prime[MX][14],tt;
map<int,int> mp;
void get_prime()
{
int n = 4e5;
for(int i = 2; i <= n; i++){
if(no_prime[i]) continue;
prime[i][++prime[i][0]] = i;
for(int j = i+i; j <= n; j+=i){
no_prime[j] = 1;
prime[j][++prime[j][0]] = i;
}
}
}
void dfs(LL &ans, int n,int p, int num, int cnt, int tail)
{
if(tail == 0) return;
int nxtnum = num*prime[p][tail];
LL k = n/nxtnum;
if(cnt&1) ans += nxtnum*k*(k+1)/2;
else ans -= nxtnum*k*(k+1)/2;
dfs(ans,n,p,num,cnt,tail-1);
dfs(ans,n,p,nxtnum,cnt+1,tail-1);
}
LL work(int n,int p)
{
LL ans = 0;
dfs(ans,n,p,1,1,prime[p][0]);
return ans;
}
void solve()
{
scanf("%d%d",&n,&m);
mp.clear();
LL ret = 0;
while(m--){
int ty,x,y,p;
scanf("%d%d%d",&ty,&x,&y);
if(ty == 1){
scanf("%d",&p);
ret = ((LL)y*(y+1)/2 - (LL)x*(x-1)/2) - (work(y,p)-work(x-1,p));
map<int,int> :: iterator it;
for(it = mp.begin(); it != mp.end(); it++) if(x <= it->fi && it->fi <= y){
if(__gcd(p,it->fi) == 1) ret -= it->fi;
if(__gcd(p,it->se) == 1) ret += it->se;
}
cout<<ret<<endl;
}
else mp[x] = y;
}
}
int main()
{
int T;
get_prime();
for(scanf("%d",&T);T;T--) solve();
return 0;
}