BZOJ3944: Sum

杜教筛
思想就是变换一下函数
杜教筛地址:
http://blog.csdn.net/skywalkert/article/details/50500009
%%%%%唐教主

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const
 ll Maxn=5030001;
ll Fai[Maxn];
int Prime[Maxn],tot;
bool Check[Maxn];
int Mu[Maxn];
const
  ll Fa=1032517,Mod=4233347;
struct Chain
{
    ll x;
    ll ans;
    Chain *next;

}*Head[Mod],*Head2[Mod]; 

inline ll Place(ll n)
{
    return (n*Fa)%Mod;
}
inline void Add(ll Pl,ll ans,ll x)
{
    Chain *tp=new Chain;
    tp->x=x;
    tp->ans=ans;tp->next=Head[Pl];
    Head[Pl]=tp; 
}
ll Ans;
inline bool find(Chain *tp,ll n)
{
    if(!tp)return false;
    if(n==tp->x){Ans=tp->ans;return true;}
    return find(tp->next,n);
} 
inline void Add2(ll Pl,ll ans,ll x)
{
    Chain *tp=new Chain;
    tp->x=x;
    tp->ans=ans;tp->next=Head2[Pl];
    Head2[Pl]=tp; 
}
inline bool find2(Chain *tp,ll n)
{
    if(!tp)return false;
    if(n==tp->x){Ans=tp->ans;return true;}
     return find(tp->next,n);
}
ll tp;
ll QueryFai(ll n)
{
    tp++;
    ll Pl;
    if(n<Maxn)return Fai[n];
    if(find(Head[Pl=Place(n)],n))return Ans;
    ll res=n*(n+1ll)>>1,di=0;
    ll Cur=2,j,t;
    while(Cur<=n)
    {
        j=n/(t=n/Cur)+1;
        di+=QueryFai(t)*(j-Cur);
        Cur=j;
    }
    Add(Pl,res-di,n);
    return res-di;
}
ll QueryMu(ll n)
{
    ll Pl;
    if(n<Maxn)return Mu[n];
    if(find2(Head2[Pl=Place(n)],n))return Ans;
    ll res=1,di=0;
    ll Cur=2,j,t;
    while(Cur<=n)
    {
        j=n/(t=n/Cur)+1;
        di+=QueryMu(t)*(j-Cur);
        Cur=j;
    }
    Add2(Pl,res-di,n);
    return res-di;
}

int main()
{
    ll i,j;
    ll k;
    Fai[1]=1;
    Mu[1]=1;
    for(i=2;i<Maxn;i++)
     {
        if(!Check[i])Prime[++tot]=i,Fai[i]=i-1,Mu[i]=-1;
        for(j=1;j<=tot;j++)
         {
            k=i*1ll*Prime[j];
            if(k>=Maxn)break;
            Check[k]=true;
            if(i%Prime[j]==0)
            {
                Mu[k]=0;
                Fai[k]=Fai[i]*Prime[j];
               break;
            }
            Mu[k]=-Mu[i];
            Fai[k]=Fai[i]*(Prime[j]-1); 
         } 
     }
    for(i=2;i<Maxn;i++)Fai[i]+=Fai[i-1];
    for(i=2;i<Maxn;i++)Mu[i]+=Mu[i-1];
    ll T;
    ll n;
    scanf("%lld",&T);
    while(T--)
    {
      scanf("%lld",&n);
      ll ans1=QueryFai(n);
      ll ans2=QueryMu(n);
      printf("%lld %lld\n",ans1,ans2);  
    }
} 

你可能感兴趣的:(BZOJ3944: Sum)