//2012金华网赛 1008
今天居然挂在了09了 ,n^3的算法 呀,不知道自己写挫了,还是爆rp了,居然老是t;话说这道题目也写得很挫。 这道题有个很好的性质1..n连续 。而且询问又很少,所以直接先求出原数组中(即1..n) 与p互质的数的和,具体肿么求可以用容斥原理。然后枚举被改变的数。
#include<stdio.h>
#include<string.h>
#include <cmath>
#include <iostream>
#include<algorithm>
#define fr(i,s,n) for(int i=s;i<n;i++)
#define pf printf
#define sf scanf
#define fi freopen("in.txt","r",stdin)
#define cl(a) memset(a,0,sizeof(a))
using namespace std;
typedef __int64 ll;
struct C{
int pos;
int val;
}c[1000];
int t;
ll prime[600],tot[400010],n;
bool flag[650];
int N,m;
void init(){
int i,j;
t=0;
int n=632;
for(i=2;i<=n;++i) {
if(!flag[i]) prime[t++]=i;
for(j=0;j<t&&i*prime[j]<=n;++j)
{
flag[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
tot[0]=0;tot[1]=1;
fr(i,2,400001) {
tot[i]=tot[i-1]+i;
}
}
ll sum(ll lim,ll x){
lim/=x;
ll ret=0;
ret=ret+(1+lim)*lim/2;
return ret*x;
}
ll yinshu[650];
int totyinshu;
void sep(ll p){
totyinshu=0;
ll tmp=p;
fr(i,0,t){
if (tmp==1) break;
if(tmp%prime[i]==0){
yinshu[totyinshu++]=prime[i];
while(tmp%prime[i]==0){
tmp/=prime[i];
}
}
}
if (tmp!=1){
yinshu[totyinshu++]=tmp;
}
}
ll dfs(int s,ll d){
ll ans=0;
while(s<totyinshu&& yinshu[s]<=n/d){
ans+=sum(n,d*yinshu[s])-dfs(s+1,d*yinshu[s]);
s++;
}
return ans;
}
int totch;
void change(int x,int y){
fr(i,0,totch){
if (c[i].pos==x){
c[i].val=y;
return ;
}
}
c[totch].pos=x;
c[totch++].val=y;
}
ll gcd(ll a,ll b){
if(b==0) return a;
return gcd(b,a%b);
}
int main(){
fi;
init();
int T,op,x,y;
ll p;
sf("%d",&T);
while(T--){
sf("%d%d",&N,&m);
totch=0;
while(m--){
sf("%d",&op);
if (op==1){
sf("%d%d%I64d",&x,&y,&p);
sep(p);
n=y;
ll ans1=tot[y]-dfs(0,1);
n=x-1;
ll ans2=tot[x-1]-dfs(0,1);
ll ans=ans1-ans2;
fr(k,0,totch){
if (c[k].pos<=y&&c[k].pos>=x){
ll tmp=gcd(c[k].val,p);
if (tmp==1) ans+=ll(c[k].val);
ll tmp1=gcd(c[k].pos,p);
if (tmp1==1) ans-=((ll)(c[k].pos));
}
}
pf("%I64d\n",ans);
}else{
sf("%d%d",&x,&y);
change(x,y);
}
}
}
return 0;
}