【BZOI 3994] [SDOI2015]数と数の約

【BZOI 3994] [SDOI2015]数と数の約

フェイス質問

集合D(x)は、Nは、Mは、尋ねる所与除数Xの数であり、\(\和_ {i = 1} ^ n個の\ sum_ {i = 1} ^ MD(iは時間j)を\ \)

Tグループは、尋ねた\(N、M、T \のLeq 50000 \)

分析

まず、結論があります

\ [D(NM)= \和_ {I | N} \和_ {J | M} [GCD(I、J)= 1] \]

約ナノメートルの数として表すことができるからである(iは時間を\ \ FRAC {M \} {J} \) の形態と、カウントを繰り返すことを確実にしないために、\(GCD(i、j)を = 1 \)

したがって、我々は、式をプッシュし始めることができます

\ [ANS = \ sum_ {P = 1} ^ n個の\ sum_ {Q = 1} ^ m個の\ sum_ {I | P} \和_ {J | Q} [GCD(I、J)= 1] \]

注目の各\((i、j)は\ ) 有するP、Q、それらが生成する複数の\(\ lfloorの\のFRAC {N } {I} \ rfloor回\ \ lfloor FRAC \ {M} {J} \ rfloor \)の貢献

\ [= \ sum_ {i = 1} ^ n個の\ sum_ {J = 1} ^ M [GCD(I、J)= 1] \ lfloor \ FRAC {n}は{I} \ rfloor \ lfloor \ FRAC {M} {J} \ rfloor \]

\ [= \ sum_ {i = 1} ^ n個の\ sum_ {J = 1} ^ m個の\ varepsilon(GCD(I、J))\ lfloor \ FRAC {n}は{I} \ rfloor \ lfloor \ FRAC {M} {J} \ rfloor \]

\(\ varepsilon(N)= \ sum_ {D | n}はミュー(D)\ \)

\ [= \ sum_ {i = 1} ^ n個の\ sum_ {J = 1} ^ M \ lfloor \ FRAC {n}は{I} \ rfloor \ lfloor \ FRAC {M} {J} \ rfloor \ sum_ {D | GCDミュー\(i、j)は}(D)\]

場合は、明らかに、和の順序、最初の列挙dを変更| \(GCD(I、J)\ D) その後、\(J \ | | dをI、D)

D iが直接J dは、複数のDV(交換、複数デュを交換+、デュ\ n型のLeq、DV \のLeq Mが\)で\(U、V \ N ^を

\ [= \ sum_ {D = 1} ^ {分(N、M)}ミュー(D)\ \ sum_ {U = 1} ^ {\ lfloor N / Dの\ rfloor} \ sum_ {V = 1} ^ { \ lfloorのM / Dの\のrfloor} \ lfloor \ FRAC {N} {デュ} \ rfloor \ lfloor \ FRAC {M} {DV} \ rfloor \]

\ [= \ sum_ {D = 1} ^ {分(N、M)}ミュー(D)\ \ sum_ {U = 1} ^ {\ lfloor N / Dの\ rfloor} \ sum_ {V = 1} ^ { \ lfloorのM / Dの\のrfloor} \ lfloor \ FRAC {\ lfloor N / Dの\ rfloor} {U} \ rfloor \ lfloor \ FRAC {\ lfloor M / Dの\のrfloor} {V} \ rfloor \]

\ [= \ sum_ {D = 1} ^ {分(N、M)}ミュー(D)\ \ sum_ {U = 1} ^ {\ lfloor N / Dの\ rfloor} \ lfloor \ FRAC {\ lfloor N / D \ rfloor} {U} \ rfloor \ sum_ {V = 1} ^ {\ lfloorのM / Dの\のrfloor} \ lfloor \ FRAC {\ lfloorのM / Dの\のrfloor} {V} \ rfloor \]

\(G(N)= \和_ {D = 1} ^ N \ lfloor \ FRAC {n}は{D} \ rfloor \)

\ [= \ sum_ {D = 1} ^ {分(N、M)}ミュー(D)G(\ lfloorの\のFRAC {n}が{D} \ rfloor)G(\ lfloorの\のFRAC {M} {D \ } \ rfloor)\]

迅速に評価する方法を検討してください。単一\(G(N)\)で数論ブロックを使用してもよい(O(\ SQRT N)\ )\ 時間で決定された、合計時間複雑度\(O(N \ SQRT N-)\) 次に、線形篩\(\ MU \) 寸法\(\ムー、G \)プレフィックスと

D列挙法の数により各質問には、総時間の複雑ブロックすることができる\(Oを(N \ SQRT N + T \ SQRT N)\)

コード

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50000
using namespace std;
typedef long long ll;
int t;
int n,m;
int cnt;
bool vis[maxn+5];
int prime[maxn+5];
int mu[maxn+5];
ll sum_mu[maxn+5];
int g[maxn+5];
void sieve(int n){
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i]){
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0){
                mu[i*prime[j]]=0;
                break;
            }else{
                mu[i*prime[j]]=-mu[i];
            }
        }
    }
    for(int i=1;i<=n;i++) sum_mu[i]=sum_mu[i-1]+mu[i];
    for(int i=1;i<=n;i++){
        int l,r;
        for(l=1;l<=i;l=r+1){
            r=i/(i/l);
            g[i]+=(ll)(r-l+1)*(i/l);
        }
    }
}

ll calc(int n,int m){
    int l,r;
    if(n<m) swap(n,m);
    ll ans=0;
    for(l=1;l<=m;l=r+1){
        r=min(n/(n/l),m/(m/l));
        ans+=(sum_mu[r]-sum_mu[l-1])*g[n/l]*g[m/l];
    }
    return ans;
}

int main(){
    sieve(maxn);
    scanf("%d",&t);
    while(t--){
        scanf("%d %d",&n,&m);
        printf("%lld\n",calc(n,m));
    }   
}

おすすめ

転載: www.cnblogs.com/birchtree/p/11360921.html