bzoj 3853 GCD Array

来源:互联网 发布:淘宝帽子女士 编辑:程序博客网 时间:2024/06/04 19:15

3853: GCD Array

Time Limit: 6 Sec  Memory Limit: 64 MB
Submit: 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

Sample Output

Case #1:
6
7

HINT

Source

By 镇海中学





【分析】
脑洞莫比乌斯反演
公式写不动,给一个链 http://www.cnblogs.com/SilverNebula/p/6991328.html
样例没过就交我也是醉了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;}