[bzoj3944] Sum "杜教筛

[bzoj3944] Sum


杜教筛板子

  • 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=6e6+10;
bool vis[N];
int prime[N/10];
int cnt;
ll phi[N],mob[N];
template <typename T>
void Write(T x) {
  if (x < 0) {
    putchar('-');
    x = -x; 
  }
  if (x > 9) Write(x / 10);
  putchar(x % 10 + '0');
}


inline void init(){
    phi[1]=1;
    mob[1]=1;
    for(int i=2;i<N;i++){
        if(!vis[i])prime[++cnt]=i,phi[i]=i-1,mob[i]=-1;
        for(int j=1;j<=cnt;j++){
            if(i*prime[j]>=N)break;
            vis[i*prime[j]]=1;
            if(i%prime[j]){
                mob[i*prime[j]]=-mob[i];
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }else{
                mob[i*prime[j]]=0;
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
        }
    }
    for(int i=2;i<N;i++)phi[i]+=phi[i-1],mob[i]+=mob[i-1];
}

map<ll,ll> PHI,MOB;

inline ll calc(ll a,ll b){
    if(a&1)return a*(b>>1);
    else return b*(a>>1);
}

ll workphi(unsigned int x){
    if(x<N)return phi[x];
    if(PHI[x])return PHI[x];
    //cout<<x<<' '<<N<<endl;
    ll ans=calc(x+1,x);
    unsigned int u,v;
    for(u=2;u<=x;u=v+1){
        v=x/(x/u);
        ans-=(v-u+1)*workphi(x/u);
    }
    return PHI[x]=ans;
}

ll workmob(unsigned int x){
    //cout<<x;
    if(x<N)return mob[x];
    if(MOB[x])return MOB[x];
    ll ans=1;
    unsigned int u,v;
    for(u=2;u<=x;u=v+1){
        v=x/(x/u);
        ans-=(v-u+1)*workmob(x/u);
    }
    return MOB[x]=ans;
}

void solve(){
    ll n;
    scanf("%lld",&n);
    ll ans1=workphi(n),ans2=workmob(n);
    Write(ans1);putchar(' ');Write(ans2);
    putchar('\n');
}

int main()
{
    init();
    int T;
    scanf("%d",&T);
    while(T--)solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/82954624