给你一个序列,支持两个操作:
- 求a的前缀和.
此时设
.
则我们需要
.
求和的时候,
此时树状数组优化一下,单次复杂度 .
#include<map>
#include<set>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define lc (x<<1)
#define rc (x<<1|1)
#define gc getchar()//(p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2)?EOF:*p1++)
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
#define IT iterator
#define SZ(a) ((int)a.size())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N=2e5+10,size=1<<20,mod=998244353;
//char buf[size],*p1=buf,*p2=buf;
template<class o> void qr(o &x) {
char c=gc; x=0; int f=1;
while(!isdigit(c)){if(c=='-')f=-1; c=gc;}
while(isdigit(c)) x=x*10+c-'0',c=gc;
x*=f;
}
template<class o> void qw(o x) {
if(x/10) qw(x/10);
putchar(x%10+'0');
}
template<class o> void pr1(o x) {
if(x<0)x=-x,putchar('-');
qw(x); putchar(' ');
}
template<class o> void pr2(o x) {
if(x<0)x=-x,putchar('-');
qw(x); puts("");
}
int n,m,mu[N],prime[N],tot; bool v[N];
ll c[N];
void add(int x,int y) {for( ;x<=n;x+=x&-x) c[x]+=y;}
ll sum(int x) {ll y=0; for( ;x;x-=x&-x) y+=c[x]; return y;}
struct edge{int d,next;} a[N*20];int len,last[N];
void ins(int x,int y) {a[++len]=(edge){y,last[x]}; last[x]=len;}
int main() {
for(int i=1;i<N;i++)
for(int j=i;j<N;j+=i)
ins(j,i);
mu[1]=1;
for(int i=2;i<N;i++) {
if(!v[i]) prime[++tot]=i,mu[i]=-1;
for(int j=1,k;(k=prime[j]*i)<N;j++) {
v[k]=1;
if(i%prime[j]==0) break;
mu[k]=-mu[i];
}
}
int T=0;
while(1) {
qr(n); qr(m);
if(!n) break;
printf("Case #%d:\n",++T);
for(int i=1;i<=n;i++) c[i]=0;
int op,x,y,z;
while(m--) {
qr(op); qr(x);
if(op==1) {
qr(y); qr(z);
if(x%y==0) for(int k=last[x/y];k;k=a[k].next) add(y*a[k].d,mu[a[k].d]*z);
}
else {
ll ans=0;
for(int l=1,r;l<=x;l=++r) {
r=x/(x/l);
ans+=(ll)(x/l)*(sum(r)-sum(l-1));
}
pr2(ans);
}
}
}
return 0;
}