P4240 毒瘤之神的考验
ANIG 不知道为啥突然做这题,【数据删除】。
description
\(Q\) 次询问,每次给定 \(n,m\),求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^m \varphi(ij)\)
- 
\(Q\leq 10^4\) 
- 
\(n,m\leq 10^5\) 
solution
一种不太要动脑子的做法。
先套路地推式子,发现原式等于 \(\sum\limits_{T=1}^{\min(n,m)} S(T,n)S(T,m)\sum\limits_{d\mid T} \dfrac{d}{\varphi(d)}\mu(\dfrac{T}{d})\),其中 \(S(a,b)=\sum\limits_{i=1}^b [a\mid i]\varphi(i)\)。
设 L 为值域,对每个数 \(p\) 处理出来 \(\lfloor\dfrac{L}{p}\rfloor\) 个位置 \(x\) 的 \(\varphi(p\times x)\) 的前缀和,这样就可以 \(O(1)\) 回答 \(S(a,b)\)。预处理的位置个数是 \(O(n\ln n)\) 的。
后面的 \(\sum\limits_{d\mid T} \dfrac{d}{\varphi(d)}\mu(\dfrac{T}{d})\) 可以预处理。
注意到对于所有 \(T\),\(S(T,n)\to S(T,n+1)\) 时,只有 \(n+1\) 的约数处的 \(T\) 的函数值会发生变化,因此我们可以 \(O(d(n+1))\) 地把答案从 \((n,m)\) 处的转移到 \((n+1,m)\) 处的。
把所有询问离线,使用莫队,设块长为 \(W\),每块内因数个数最多的数的因数个数平均是 \(d\),即可做到 \(O(\dfrac{L}{W}\times L\times \log L+Q\times W\times d)\)。实际上 \(d\) 大概和 \(\log L\) 相当。
故取 \(W=\dfrac{L}{\sqrt{Q}}\) 有最优复杂度 \(O(L\sqrt{Q}\log L)\)。
code
#include<bits/stdc++.h>
using namespace std;
using E=long long;
constexpr E mod=998244353;
E T=1e5;
vector<E> phi,miu,f,primes,st;
E ksm(E a,E b){
  E ret=1;
  while(b){
    if(b&1) ret=ret*a%mod;
    a=a*a%mod;
    b>>=1;
  }
  return ret;
}
int main(){
  cout.tie(nullptr),cin.tie(nullptr)->sync_with_stdio(false);
  phi=miu=f=st=vector<E>(T+1);
  phi[1]=miu[1]=1;
  for(int i=2; i<=T; i++){
    if(!st[i]){
      primes.emplace_back(i);
      phi[i]=i-1;
      miu[i]=-1;
    }
    for(auto j:primes){
      if(i*j>T) break;
      st[i*j]=1;
      if(i%j==0){
        miu[i*j]=0;
        phi[i*j]=phi[i]*j;
        break;
      }
      phi[i*j]=phi[i]*phi[j];
      miu[i*j]=miu[i]*miu[j];
    }
  }
  for(int i=1; i<=T; i++) miu[i]=(miu[i]%mod+mod)%mod;
  vector<vector<int>> divis(T+1);
  vector<vector<E>> sum(T+1);
  for(int i=1; i<=T; i++){
    E coef=i*ksm(phi[i],mod-2)%mod;
    for(int j=i; j<=T; j+=i){
      f[j]=(f[j]+coef*miu[j/i]%mod)%mod;
      divis[j].emplace_back(i);
    }
  }
  for(int i=1; i<=T; i++){
    sum[i].emplace_back(0);
    for(int j=i; j<=T; j+=i){
      sum[i].emplace_back(sum[i].back()+phi[j]);
      sum[i][sum[i].size()-1]%=mod;
    }
  }
  struct querys{
    int l,r;
    int idx;
    querys(int x=0,int y=0,int z=0){
      l=x,r=y,idx=z;
    }
  };
  vector<querys> Q;
  int q;
  cin>>q;
  for(int i=1; i<=q; i++){
    int l,r;
    cin>>l>>r;
    Q.emplace_back(querys(l,r,i));
  }
  int bksz=450;
  sort(Q.begin(),Q.end(),[&](const querys &x,const querys &y)->bool{
          if((x.l/bksz)==(y.l)/bksz){
            return (bool)(((x.l/bksz)&1)^(x.r<y.r));
          }
          return x.l<y.l;
       });
  int l,r;
  E ans=0;
  l=r=ans=1;
  auto add=[&](int m,int pos,int op)->void{
    E x=0;
    for(auto p:divis[pos]){
      x=(x+phi[pos]*(sum[p][m/p])%mod*f[p])%mod;
    }
    x=x*op%mod;
    ans=(ans+x)%mod;
  };
  vector<E> res(q+1);
  for(int tt=0; tt<q; tt++){
    int L=Q[tt].l,R=Q[tt].r;
    while(l<L){
      add(r,l+1,1);
      l++;
    }
    while(l>L){
      add(r,l,mod-1);
      l--;
    }
    while(r<R){
      add(l,r+1,1);
      r++;
    }
    while(r>R){
      add(l,r,mod-1);
      r--;
    }
    res[Q[tt].idx]=ans;
  }
  for(int i=1; i<=q; i++) cout<<res[i]<<'\n';
  return 0;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号