P2522 [HAOI2011]問題、B

タイトル説明

nに与えられた質問、(x、y)の数の数を求めてそれぞれ、a≤x≤b、c≤y≤d、およびGCD(X、Y)= K、GCD(X、Yを満たします)xとyの最大公約数の関数として示します。

入力形式

最初のラインnは整数、次の5行の各整数nは、それぞれ、A、B、C、D、K

出力フォーマット

n行の合計、各行(x、y)の数の要件を満たす整数の

説明/ヒント

100%のデータを満たす:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000

サンプル入力と出力

エントリー

2
2 5 1 5 1
1 5 1 5 2

輸出

14
3

この質問は必要とされ

\ [\和\ limits_ {X = A} ^ {B} \合計\ limits_ {Y = C} ^ {D} [\ GCD(X、Y)== K] \]

被写体が同じように感じるでしょう参照してください[P3455 ZAP-クエリ]が、この質問\(X- \)、\ (y軸の\)を開始するための1から列挙型の範囲ではありません。

だから私たちが書いた当初から、我々は最初から問題に変換することもできます。

二次元の接頭辞と包除原理を考えるの種類と同様に...我々は得ることができます

\ [\和\ limits_ {X = 1} ^ {B} \和\ limits_ {Y = 1} ^ {D} - \和\ limits_ {X = 1} ^ { - 1} \和\ limits_ {Y = 1} ^ {D} - \和\ limits_ {X = 1} ^ {B} \和\ limits_ {Y = 1} ^ {C-1} + \和\ limits_ {X = 1} ^ {A- 1} \和\ limits_ {Y = 1} ^ {C-1} \]

(私は精通していないように、あなたはスタイルの上にマップを描くことができます)

遅延のために、我々はそれを処理するための関数を書く(F(M、N)\ = \和の\ limits_ {X = 1} ^ {M} \和の\ limits_ {Y = 1} ^ {N} [\ GCD(X 、Y)== K] \)

(練習は完璧になり、再び数式を導き出すために書きます)

参照\([\ GCD(X、 Y)== K] \) が考えられるが提案\(K \)\(I(\ GCD(X、Y))\) および\(I = \ミュー* U \)

\ [\和\ limits_ {X = 1} ^ {M / K} \和\ limits_ {Y = 1} ^ {N / K} [\ GCD(X、Y)== 1] \]

\ [\和\ limits_ {X = 1} ^ {M / K} \和\ limits_ {Y = 1} ^ {N / K} \和\ limits_ | MU \ {D \ GCD(X、Y)}( D)\]

参照\(D | [\ GCD( X、Y)] \) 以下の合計では、列挙型を与えたことができます

\ [\和\ limits_ {X = 1} ^ {M / K} \和\ limits_ {Y = 1} ^ {N / K} \和\ limits_ {D = 1} ^ {\分(\ FRAC {M } {K}、ミュー\ \のFRAC {N} {K})}(D)[D | \ GCD(X、Y)] \]

そして、私たちは知っている、それは二つの数因子の要因公約数でなければなりません\(| = [D | | X] \ [Y D] [\のGCD(X、Y)D])ので、

\ [\和\ limits_ {X = 1} ^ {M / K} \和\ limits_ {Y = 1} ^ {N / K} \和\ limits_ {D = 1} ^ {\分(\ FRAC {M } {K}、ミュー\ \のFRAC {N} {K})}(D)[D | X] [D | Y] \]

いいえ合計は、異なる列挙順序についていじることはどんな関係を持っていないようです!

\ [\和\ limits_ {D = 1} ^ {\分(\ FRAC {M} {K}の\ FRAC {N} {K})}ミュー(D)\和\ \ limits_ {X = 1} ^ {M / K} [D | X] \和\ limits_ {Y = 1} ^ {N / K} [D | Y] \]

\(\和\ limits_ {X = 1} ^ {M / K} [D | X] = \和\ limits_ {X = 1} ^ {M / K} \和\ limits_ {D | X} 1 = \ lfloorの\のFRAC {M} {K \ CDOT D} \ rfloor \)、所以

MU(D)\ lfloor \ FRAC {M} {K \ \ [\和の\ limits_ {D = 1} ^ {\分(\ FRAC {M} {K}の\ FRAC {N} {K})} \ CDOT D} \ rfloor \ lfloor \ FRAC {n}は{K \ CDOT D} \ rfloor \]

コードは以下の通りであります:

#include <bits/stdc++.h>

using namespace std;

const int maxn=5e4;
typedef long long ll;

int prime[maxn+10];
int mu[maxn+10];
int vis[maxn+10];
int sum[maxn+10];

int k;

void sieve(){
    int p=0;
    mu[1]=1;
    for(int i=2;i<=maxn;i++){
        if(!vis[i]){
            vis[i]=1;
            prime[++p]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=p&&i*prime[j]<=maxn;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)break;
            else mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<=maxn;i++){
        sum[i]=sum[i-1]+mu[i];
    }
}

ll f(int m, int n){
    ll ans=0;
    int tmp=min(m/k,n/k);
    for(int l=1;l<=tmp;){
        int r=min(m/(m/l),n/(n/l));
        ans+=(ll)(sum[r]-sum[l-1])*(ll)(m/k/l)*(ll)(n/k/l);
        l=r+1;
    }
    return ans;
}

int main()
{
    memset(vis,0,sizeof(vis));
    sieve();
    int a,b,c,d,t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        cout<<f(b,d)-f(a-1,d)-f(b,c-1)+f(a-1,c-1)<<endl;
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/tongseli/p/11682038.html