3853: GCD Array
Time Limit: 6 Sec Memory Limit: 64 MBSubmit: 341 Solved: 130
[ Submit][ Status][ Discuss]
Description
Teacher Mai finds that many problems about arithmetic function can be reduced to the following problem:
Maintain an array a with index from 1 to l. There are two kinds of operations:
1. Add v to ax for every x that gcd(x,n)=d.
2. Query Sigma(Xi) (i<=1<=X)
Input
There are multiple test cases, terminated by a line "0 0".
For each test case, the first line contains two integers l,Q(1<=l,Q<=5*10^4), indicating the length of the array and the number of the operations.
In following Q lines, each line indicates an operation, and the format is "1 n d v" or "2 x" (1<=n,d,v<=2*10^5,1<=x<=l).
Output
For each case, output "Case #k:" first, where k is the case number counting from 1.
Then output the answer to each query.
Sample Input
6 4
1 4 1 2
2 5
1 3 3 3
2 3
0 0
1 4 1 2
2 5
1 3 3 3
2 3
0 0
Sample Output
Case #1:
6
7
6
7
HINT
Source
【分析】
脑洞莫比乌斯反演
样例没过就交我也是醉了QAQ
【代码】
//bzoj 3853 GCD Array
#include<bits/stdc++.h>
#define N 200000
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=200005;
vector <int> f[mxn];
int n,m,Q,T,x,d,v;
bool vis[mxn];
int pri[mxn],mu[mxn];
ll c[mxn];
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x;
}
inline int lowbit(int x) {return x&-x;}
inline void add(int u,ll v)
{
for(int i=u;i<=n;i+=lowbit(i)) c[i]+=v;
}
inline ll getsum(int u)
{
ll sum=0;
for(int i=u;i>=1;i-=lowbit(i))
sum+=c[i];
return sum;
}
inline void init()
{
int i,j;
mu[1]=1;
fo(i,2,N)
{
if(!vis[i]) pri[++pri[0]]=i,mu[i]=-1;
for(j=1;j<=pri[0]&&(ll)i*pri[j]<=N;j++)
{
vis[i*pri[j]]=1;
if(i%pri[j]==0) break;
mu[i*pri[j]]=-mu[i];
}
}
fo(i,1,N)
for(j=i;j<=N;j+=i)
f[j].push_back(i);
}
inline ll solve(int x)
{
ll ans=0;
for(int i=1,last=0;i<=x;i=last+1)
{
last=x/(x/i);
ans+=(getsum(last)-getsum(i-1))*(x/i);
}
return ans;
}
int main()
{
init();
int i,j,k,opt;
while(n=read(),m=read())
{
if(!n && !m) return 0;
memset(c,0,sizeof c);
printf("Case #%d:\n",++T);
while(m--)
{
opt=read();
if(opt==1)
{
x=read(),d=read(),v=read();
if(x%d!=0) continue;k=x/d;
for(i=0;i<f[k].size();i++)
add((ll)f[k][i]*d,(ll)v*mu[f[k][i]]);
}
else
{
x=read();
printf("%lld\n",solve(x));
}
}
}
return 0;
}