Problem 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 a x for every x that gcd(x,n)=d.
2. Query
Maintain an array a with index from 1 to l. There are two kinds of operations:
1. Add v to a x for every x that gcd(x,n)=d.
2. Query
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).
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.
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
Sample Output
Case #1: 6 7
Source
#include <cstdio>
#include <vector>
using namespace std;
long long node[50005];
int mu[200001],prime[200001],l,Q;
bool check[200001];
vector<int>fact[200001];
void Mobius()
{
int i,j,cnt;
cnt=0;
mu[1]=1;
for(i=2;i<=200000;i++)
{
if(!check[i])
{
prime[cnt++]=i;
mu[i]=-1;
}
for(j=0;j<cnt;j++)
{
if(i*prime[j]>200000) break;
check[i*prime[j]]=1;
if(i%prime[j]) mu[i*prime[j]]=-mu[i];
else break;
}
}
for(i=1;i<=200000;i++) for(j=i;j<=200000;j+=i) fact[j].push_back(i);//求因子
}
void add(int x,int v)
{
while(x<=l)
{
node[x]+=v;
x+=x&-x;
}
}
long long sum(int x)
{
long long res=0;
while(x>0)
{
res+=node[x];
x-=x&-x;
}
return res;
}
int main()
{
int cases=1,t,n,d,v,i,last;
long long ans,temp,lasttemp;
Mobius();
while(scanf("%d%d",&l,&Q) && l)
{
for(i=0;i<=l;i++) node[i]=0;
printf("Case #%d:\n",cases++);
while(Q--)
{
scanf("%d",&t);
if(t==1)
{
scanf("%d%d%d",&n,&d,&v);
if(n%d) continue;
n/=d;
for(i=0;i<fact[n].size();i++)
{
t=fact[n][i];
add(t*d,mu[t]*v);
}
}
else
{
scanf("%d",&n);
ans=0;
temp=0;
for(i=1;i<=n;i=last+1)
{
last=n/(n/i);
lasttemp=temp;//分块加速
temp=sum(last);
ans+=n/i*(temp-lasttemp);
}
printf("%I64d\n",ans);
}
}
}
}