zoukankan      html  css  js  c++  java
  • 杜教筛

    解决问题:已知(f(i))是积性函数,求(sumlimits_{i=1}^nf(i))

    (S(n)=sumlimits_{i=1}^nf(i))

    再找一个积性函数(g()),求(f*g)的前缀和:
    (sumlimits_{i=1}^{n}(f*g)(i))
    (=sumlimits_{i=1}^{n}sumlimits_{d|i}f(d)*g(frac{i}{d}))
    (=sumlimits_{d=1}^{n}g(d)sumlimits_{i=1}^{frac{n}{d}}f(i))
    (=sumlimits_{d=1}^{n}g(d)*S(frac{n}{d}))

    考虑(g(1)S(n))
    (g(1)S(n))
    (=sumlimits_{i=1}^{n}g(i)*S(frac{n}{i})-sumlimits_{i=2}^{n}g(i)*S(frac{n}{i}))
    (=sumlimits_{i=1}^{n}(f*g)(i)-sumlimits_{i=2}^{n}g(i)*S(frac{n}{i}))

    发现只要找到一个合适的积性函数(g)满足可以快速求(f*g)(g)的前缀和,那么就可以结合除法分块递归求解(sumlimits_{i=1}^{n}f(i))

    复杂度为(O(n^{frac{3}{4}}))

    优化:
    1.线性筛前(n^{frac{2}{3}})个答案,复杂度为(O(n^{frac{2}{3}}))
    2.中途用哈希表记录答案。

    例子:
    1.求(sumlimits_{i=1}^{n}varphi(i))

    ((varphi*1=id)),令(f=varphi,g=1,f*g=id)

    2.求(sumlimits_{i=1}^{n}mu(i))

    (mu*1=epsilon),令(f=mu,g=1,f*g=epsilon)

    模板题
    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=5000010;
    int T,n;
    int mu[maxn],sum2[maxn],phi[maxn];
    ll sum1[maxn];
    bool vis[maxn];
    vector<int>prime;
    unordered_map<int,ll>mp1;
    unordered_map<int,int>mp2;
    inline void pre_work(int n)
    {
    	vis[1]=1;mu[1]=phi[1]=1;
    	for(int i=2;i<=n;i++)
    	{
    		if(!vis[i])prime.push_back(i),mu[i]=-1,phi[i]=i-1;
    		for(unsigned int j=0;j<prime.size()&&1ll*i*prime[j]<=n;j++)
    		{
    			vis[i*prime[j]]=1;
    			if(i%prime[j]==0)
    			{
    				phi[i*prime[j]]=phi[i]*prime[j];
    				break;
    			}
    			phi[i*prime[j]]=phi[i]*(prime[j]-1);
    			mu[i*prime[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=n;i++)sum1[i]=sum1[i-1]+phi[i],sum2[i]=sum2[i-1]+mu[i];
    }
    inline ll getphi(ll n)
    {
    	if(n<=5000000)return sum1[n];
    	if(mp1.count(n))return mp1[n];
    	ll res=1ll*n*(n+1)/2;
    	for(ll l=2,r;l<=n;l=r+1)
    	{
    		r=n/(n/l);
    		res-=1ll*(r-l+1)*getphi(n/l);
    	}
    	return mp1[n]=res;
    }
    inline int getmu(int n)
    {
    	if(n<=5000000)return sum2[n];
    	if(mp2.count(n))return mp2[n];
    	int res=1;
    	for(int l=2,r;l<=n;l=r+1)
    	{
    		r=n/(n/l);
    		res-=(r-l+1)*getmu(n/l);
    	}
    	return mp2[n]=res;
    }
    int main()
    {
    	//freopen("test.in","r",stdin);
    	//freopen("test.out","w",stdout);
    	pre_work(5000000);
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d",&n);
    		printf("%lld %d
    ",getphi(n),getmu(n));
    	}
    	return 0;
    }
    
  • 相关阅读:
    ceph
    分布式网关层
    function declarations are hoisted and class declarations are not 变量提升
    js为Object对象动态添加属性和值 eval c.k c[k]
    方法就是一种变量
    static 不被实例调用
    WePY根据环境变量来改变运行时的参数
    函数类型实现接口——把函数作为接口来调用
    为什么需要onRoute函数?
    504 Gateway Timeout Error 502 Bad Gateway
  • 原文地址:https://www.cnblogs.com/nofind/p/11953085.html
Copyright © 2011-2022 走看看