【模板】杜教筛(Sum)

传送门

Description

给定一个正整数\(N(N\le2^{31}-1)\)

\[ans1=\sum_{i=1}^n \varphi(i)\]

\[ans_2=\sum_{i=1}^n \mu(i)\]

Solution

总算是写了一个不会\(TLE\)的杜教筛,不想用\(map\),因此上了一个很丑的\(Hash\)……


Code

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define MN 1900000
int cnt,pr[MN];
bool mark[MN];
struct Node{int id;ll phi,mu;}MI[MN];
inline void init()
{
    register int i,j;
    for(i=1;i<MN;++i) MI[i].id=i;
    MI[1].phi=MI[1].mu=1;
    for(i=2;i<MN;++i)
    {
        if(!mark[i]){pr[++cnt]=i;MI[i].phi=i-1;MI[i].mu=-1;}
        for(j=1;j<=cnt&&i*pr[j]<MN;++j)
        {
            #define now i*pr[j]
            mark[now]=true;
            if(i%pr[j]==0){MI[now].mu=0;MI[now].phi=MI[i].phi*pr[j];break;}
            else MI[now].mu=-MI[i].mu,MI[now].phi=MI[i].phi*(pr[j]-1);
            #undef now
        }
    }
    for(i=1;i<MN;++i) MI[i].phi+=MI[i-1].phi,MI[i].mu+=MI[i-1].mu;
}
class Hash
{
    #define mod 23333
    private:
        std::vector<Node> a[mod];
        int ha,i;
        Node em;
    public:
        Hash(){em=(Node){0,0ll,0ll};};
        inline void insert(int id,ll phi,ll mu){a[id%mod].push_back((Node){id,phi,mu});}
        inline Node find(int id)
        {
            ha=id%mod;
            for(i=a[ha].size()-1;~i;--i) if(a[ha][i].id==id) return a[ha][i];
            return em;
        }
}HA;
inline Node calc(int n)
{
    if(n<MN) return MI[n];
    register Node ans,tmp;
    if((ans=HA.find(n)).id) return ans;
    ll ret1=1ll,ret2=1ll*n*(n+1)/2ll;
    for(register ll i=2,j;i<=n;i=j+1)
        j=n/(n/i),tmp=calc(n/i),ret1-=(j-i+1)*tmp.mu,ret2-=(j-i+1)*tmp.phi;
    ans=(Node){n,ret2,ret1};HA.insert(n,ret2,ret1);
    return ans;
}
int main()
{
    init();
    register int T,n;
    T=read();
    register Node ans;
    while(T--)
    {
        n=read();
        ans=calc(n);
        printf("%lld %lld\n",ans.phi,ans.mu);
    }
    return 0;
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

猜你喜欢

转载自www.cnblogs.com/PaperCloud/p/10242121.html