zoukankan      html  css  js  c++  java
  • bzoj 3853 : GCD Array

    搬运题解
    Claris:
    1 n d v相当于给$a[x]+=v[gcd(x,n)=d]$

    $egin{eqnarray*}&&v[gcd(x,n)=d]\&=&v[gcd(frac{x}{d},frac{n}{d})=1]\&=&vsum_{k|gcd(frac{x}{d},frac{n}{d})}mu(k)\&=&sum_{k|frac{n}{d},dk|x}vmu(k)end{eqnarray*}$
    设 $a[i]=sum_{j|i}f[j]$
    则每次修改相当于枚举$k|frac{n}{d}$,然后给$f[dk]+=vmu(k)$
    查询$x=sum_{i=1}^x a[i]=sum_{i=1}^xsum_{d|i}f[d]=sum_{d=1}^x f[d]frac{x}{d}$
    可以分块统计,用树状数组维护f[]的前缀和

    大概维护一个数列
    支持
    1.对所有x的倍数的位置加上v
    2.查询前缀和
    可以用分块的方法把复杂度降为$nsqrt{n}logn$

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #define ll long long
    #define pb(x) push_back(x)
    #define N 200005
    using namespace std;
    int n,q;
    int su[N],tot,pr[N],miu[N];
    const int inf = 200000;
    vector<int>v[N];
    void shai()
    {
    	miu[1]=1;
    	for(int i=1;i<=inf;i++)v[i].pb(1);
    	for(int i=2;i<=inf;i++)
    	{
    		if(!pr[i])
    		{
    			pr[i]=i;
    			su[++tot]=i;
    			miu[i]=-1;
    		}
    		for(int j=1;j<=tot&&su[j]*i<=inf;j++)
    		{
    			pr[su[j]*i]=su[j];
    			if(su[j]==pr[i])
    			{
    				break;
    			}
    			else miu[su[j]*i]=-miu[i];
    		}
    		for(int j=i;j<=inf;j+=i)v[j].pb(i);
    	}
    	return ;
    }
    ll c[N];
    void add(int x,int z)
    {
    	for(int i=x;i<=n;i+=(i&(-i)))
    	{
    		c[i]+=z;
    	}
    	return ;
    }
    ll qur(int x)
    {
    	ll ans=0;
    	for(int i=x;i;i-=(i&(-i)))
    	{
    		ans+=c[i];
    	}
    	return ans;
    }
    int main()
    {
    	shai();int cnt=0;
    	while(~scanf("%d%d",&n,&q))
    	{
    		if(!n&&!q)break;
    		printf("Case #%d:
    ",++cnt);
    		for(int i=1;i<=n;i++)c[i]=0;
    		int t1,t2,t3,t4;
    		for(int i=1;i<=q;i++)
    		{
    			scanf("%d",&t1);
    			if(t1==1)
    			{
    				scanf("%d%d%d",&t2,&t3,&t4);
    				if(t2%t3!=0)continue;
    				int num=t2/t3;
    				for(int j=0;j<v[num].size();j++)
    				{
    					int k=v[num][j];
    					add(k*t3,miu[k]*t4);
    				}
    			}
    			else 
    			{
    				scanf("%d",&t2);
    				ll ans=0;int r;
    				for(int l=1;l<=t2;l=r+1)
    				{
    					r=t2/(t2/l);
    					ans+=1LL*(t2/l)*(qur(r)-qur(l-1));
    				}
    				printf("%lld
    ",ans);
    			}
    			
    		}
    		
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Code Forces Gym 100886J Sockets(二分)
    CSU 1092 Barricade
    CodeChef Mahesh and his lost array
    CodeChef Gcd Queries
    CodeChef GCD2
    CodeChef Sereja and LCM(矩阵快速幂)
    CodeChef Sereja and GCD
    CodeChef Little Elephant and Balance
    CodeChef Count Substrings
    hdu 4001 To Miss Our Children Time( sort + DP )
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6781631.html
Copyright © 2011-2022 走看看