[SDOI2015]約數個數和-[BZOJ4176]Lucas的數論-題解

VictoryCzt發表於2018-12-19

[SDOI2015]約數個數和

題意簡述

給定n,mn,m,求下面式子的值,其中σ0(i)\sigma_0(i)表示ii的約數個數。

i=1nj=1mσ0(ij) \sum_{i=1}^n\sum_{j=1}^m\sigma_0(ij)

其中n,m50000n,m\leq 50000


我們考慮將σ0(ij)\sigma_0(ij)進行轉化,其實其值就相當於下面:

σ0(ij)=xiyj[gcd(x,y)=1] \sigma_0(ij)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]

簡單證明:

由於其質因子之間會不影響,所以我們分開單獨考慮,對於一個ijij的質因子pp,假設它在ijij中為pcp^c,那麼肯定有pai,pbj,a+b=cp^a|i,p^b|j,a+b=c,所以我們考慮,對於一個因子pdp^d,如果dad\leq a我們就在ii中選擇,此時pdxp^d|x,那麼由於對於這一個因子只能算一次,所以在xx中選了後就不能再yy中選擇,所以必須保證yy中沒有因子pp,而當d>ad> a時,我們就在yy中選擇指數為dad-a的,此時同樣要求xx中不包含因子pp,那麼將此情況應用到所有的質因子上,顯然xyx\perp y,也就是gcd(x,y)=1gcd(x,y)=1,因此得證。

其實相當於一個對映,我們將pdp^d,其中dad\leq a的對映到xx上去,而d>ad> a的對映到yy上,由於如果x,yx,y不互質,那麼相當於我們把同一個因子同時對映在了x,yx,y,會算多次,但是隻能算一次,所以要保證互質。

那麼我們就將式子轉換成了(這裡預設nmn\leq m不滿足則交換):

i=1nj=1mxiyj[gcd(x,y)=1]i=1nj=1mxiyjwx,wyμ(w)w=1nμ(w)i=1nwj=1mwnwimwj \sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}[gcd(x,y)=1] \\ \sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}\sum_{w|x,w|y}\mu(w) \\ \sum_{w=1}^n\mu(w)\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{w}\rfloor}\left\lfloor\frac{n}{wi}\right\rfloor\left\lfloor\frac{m}{wj}\right\rfloor

由於n,mn,m的範圍比較小,我們線性篩出μ\mu並預處理字首和,然後對於後面的我們令g(n)=i=1nnig(n)=\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor

其實我們容易知道:
g(n)=i=1nni=i=1nσ0(i) g(n)=\sum_{i=1}^n\left\lfloor\frac{n}{i}\right\rfloor=\sum_{i=1}^n\sigma_0(i)

簡單證明:

我們考慮,對於一個ii,它可以對其倍數,也就是2i,3i, ,nii2i,3i,\cdots,\lfloor\frac{n}{i}\rfloor i,貢獻ni\lfloor\frac{n}{i}\rfloor次,剛好反過來考慮,對於一個數ii,它的每個因子都會對其貢獻一次,所以原式就相等了。

原式就變成:

w=1nμ(w)g(nw)g(mw) \sum_{w=1}^n\mu(w)g(\lfloor\frac{n}{w}\rfloor)g(\lfloor\frac{m}{w}\rfloor)

那麼我們再O(n)O(n)的線性篩出σ0\sigma_0並預處理字首和,這個題就可以每次分塊的回答了。

複雜度O(n+Tn)O(n+T\sqrt n)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=1e5+10;
int T,n,m;
ll prime[M],sdiv[M],num[M],cnt,mob[M];
bool nop[M];
void init(int n){
  sdiv[1]=1;num[1]=1;mob[1]=1;
  for(int i=2;i<=n;i++){
    if(!nop[i]) prime[++cnt]=i,sdiv[i]=2,num[i]=1,mob[i]=-1;
    for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
      nop[i*prime[j]]=1;
      if(i%prime[j]){
        sdiv[i*prime[j]]=sdiv[i]*sdiv[prime[j]];
        num[i*prime[j]]=1;
        mob[i*prime[j]]=-mob[i];
      }else{
        sdiv[i*prime[j]]=sdiv[i]/(num[i]+1)*(num[i]+2);
        num[i*prime[j]]=num[i]+1;
        mob[i*prime[j]]=0;
        break;
      }
    }
  }
  for(int i=1;i<=n;i++) sdiv[i]+=sdiv[i-1],mob[i]+=mob[i-1];
}
ll calc(int n,int m){
  int pos;if(n>m) swap(n,m);
  ll ans=0;
  for(int i=1;i<=n;i=pos+1){
    int t1=n/i,t2=m/i;
    pos=min(n/(t1),m/(t2));
    ans+=(mob[pos]-mob[i-1])*(sdiv[t1])*(sdiv[t2]);
  }
  return ans;
}
int main(){
  scanf("%d",&T);
  init(50000);
  while(T--){
    scanf("%d%d",&n,&m);
    printf("%lld\n",calc(n,m));
  }
  return 0;
}

加強版【BZOJ4176-許可權題

一組詢問,給定n109n\leq 10^9,求下面式子的值:

i=1nj=1nσ0(ij) \sum_{i=1}^n\sum_{j=1}^n\sigma_0(ij)

此時無法O(n)O(n)的線性篩,所以我們要換個角度考慮,可能要用杜教篩或其他低於線性的篩法。


我們先來看σ0(ij)\sigma_0(ij),對於一個dijd|ij,我們令a=igcd(i,d),b=dgcd(i,d)a=\frac{i}{gcd(i,d)},b=\frac{d}{gcd(i,d)},此時顯然aba\perp b,然後肯定有ai,bja|i,b|jaia|i是顯然的,而bjb|j由於dijd|ijbdb|dbb只是除去了在ii中的因子,所以肯定bjb|j)。

另外一種解釋:b×gcd(i,d)=db\times gcd(i,d)=ddijbijgcd(i,d)=bajd|ij\Leftrightarrow b|\frac{ij}{gcd(i,d)} = b|aj,因為aba\perp b,所以bjb|j

所以,對於任意ab,ai,bja\perp b,a|i,b|j的都有d=ibaijd=\frac{ib}{a}|ij,由此可知:

σ0(ij)=dij1=ai,bj,ab1=ai,bj[gcd(i,j)=1] \sigma_0(ij)=\sum_{d|ij}1=\sum_{a|i,b|j,a\perp b}1=\sum_{a|i,b|j}[gcd(i,j)=1]

這個也就是前面的另一種數學的證明方法,再說一遍而已XD


我們看原來化簡到最後的式子,此時就變成了:

w=1nμ(w)(g(nw))2 \sum_{w=1}^n\mu(w)(g\left(\left\lfloor\frac{n}{w}\right\rfloor\right))^2

對於μ\mu的字首和我們用杜教篩就可以了,而對於g(n)g(n)的值,我們預處理n23n^{\frac{2}{3}}個,然後每次呼叫到更大的,現場數論分塊O(n)O(\sqrt n)的算就好啦,記憶化一下。

由於杜教篩中也有數論分塊,所以複雜度還是O(n23)O(n^{\frac{2}{3}}),那麼這個題就解決了。

程式碼,先咕咕一會兒XD


End

一道類似的題目【51Nod1220約數之和】-【題解

相關文章