P4213模板杜教筛

Posted shxnb666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4213模板杜教筛相关的知识,希望对你有一定的参考价值。

题面

https://www.luogu.org/problem/P4213

题解

#include<cstdio>
#include<iostream>
#include<cstring>
#pragma GCC optimize(2)
#define ri register int
#define maxn 2147483647
#define maxm 3000000
#define maxk 2000
#define LL long long

using namespace std;

int p[maxm],phi[maxm],miu[maxm],k[maxm],prime[maxm],cnt=0;
bool vis[maxm];
LL S1[maxm],S2[maxk];

LL SS1[maxm],SS2[maxk];
bool vis2[maxm];

int T,N;

void getS1() 
  phi[1]=1;
  for (ri i=2;i<maxm;i++) 
    if (p[i]==0) 
      k[i]=p[i]=prime[++cnt]=i;
      phi[i]=i-1;
    
    for (ri j=1;j<=cnt && i*prime[j]<maxm;j++) 
      k[i*prime[j]]=p[i*prime[j]]=prime[j];
      phi[i*prime[j]]=phi[i]*phi[prime[j]];
      if (prime[j]==p[i]) 
        k[i*prime[j]]*=k[i];
        phi[i*prime[j]]=phi[i/k[i]]*phi[prime[j]*k[i]];
        if (k[i*prime[j]]==i*prime[j]) phi[i*prime[j]]=i*(prime[j]-1);
        break;
      
    
  
  S1[0]=0;
  for (ri i=1;i<maxm;i++) S1[i]=S1[i-1]+phi[i];


  miu[1]=1;
  for (ri i=2;i<maxm;i++) 
    if (i==p[i]) miu[i]=-1;
    else if (k[i]==i) miu[i]=0;
    else miu[i]=miu[i/k[i]]*miu[k[i]];
  
  SS1[0]=0;
  for (ri i=1;i<maxm;i++) SS1[i]=SS1[i-1]+miu[i];


LL S(int n) 
  if (n<maxm) return S1[n];
  ri x=N/n;
  if (x<maxk && vis[x]) return S2[x];
  vis[x]=true;
  LL &ans=S2[x];
  ans=(LL)n*(n+1)/2;
  for (ri i=2,j;i<=n;i=j+1) 
    j=n/(n/i);
    ans-=(j-i+1)*S(n/i);
  
  return ans;


LL SS(int n) 
  if (n<maxm) return SS1[n];
  ri x=N/n;
  if (x<maxk && vis2[x]) return SS2[x];
  vis2[x]=true;
  LL &ans=SS2[x];
  ans=(LL)1;
  for (ri i=2,j;i<=n;i=j+1) 
    j=n/(n/i);
    ans-=(j-i+1)*SS(n/i);
  
  return ans;


int main()
  scanf("%d",&T);
  getS1();
  for (ri i=1;i<=T;i++) 
    scanf("%d",&N);
    memset(vis,0,sizeof(vis));
    memset(vis2,0,sizeof(vis2));
    printf("%lld %lld\n",S(N),SS(N));
  

 

以上是关于P4213模板杜教筛的主要内容,如果未能解决你的问题,请参考以下文章

P4213 模板杜教筛(Sum)

P4213 模板杜教筛(Sum) min_25筛

洛谷P4213 Sum(杜教筛)

luoguP4213 [模板]杜教筛

模板杜教筛

模板杜教筛(Sum)