整除分塊


整除分塊

前言

因為最近在學習莫比烏斯反演,發現整除分塊這個東西幾乎是非常必要的,因為是真的好用,可以把一些需要\(O(n)\)的枚舉優化到\(O(\sqrt n)\)

正文

什么式子可以用整除分塊呢?一般是這樣

\[\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor \]

我們發現(打表或者是自己yy),對於一段連續的區間,\(\lfloor\frac{n}{i}\rfloor\)的值是不變的,那么對於這一段區間,我們就可以跳過,\(O(1)\)計算出這一段區間的值

既然是分塊,那么一塊的邊界是什么呢?
首先,明確一點,首端點l是枚舉出來的,而末端點是\(n/(n/l)\)(感性理解一下)
而據dalao分析,時間復雜度是\(O(\sqrt n)\),有了這個范圍,我們就可以分塊了

Code

inline void init (int ans=0) {
    for(int l=1,r,len;l<=n;l=r+1) {
        r=n/(n/l),len=r-l+1;
        ans+=len*(n/l);
    }
}

應用

很多時候,整除分塊是配合其他一些函數來用的,such as \(\mu\),\(\phi\)...
當我們的區間跳躍的時候,函數值也會跳躍,所以就要記得乘上這一段區間的函數值,這個時候就需要前綴和優化了
聽dalao說,有些惡心的題目會卡線性篩(T飛),這個時候就需要杜教篩,你問我杜教篩是什么?問得好,我也不知道(逃~是真的,以后有時間再補吧)

例題

放幾道整除分塊的例題
[AHOI2005]約數研究
[CQOI2007]余數求和
洛谷P3935 Calculating
第一題沒什么思路,直接預處理,在這里放一下代碼

Code

#include<bits/stdc++.h>
#define il inline
#define rg register
#define lol long long
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)?(b)?(a):(b)

using namespace std;

void in(int &ans) {
    ans=0; char i=getchar();
    while(i<'0' || i>'9') i=getchar();
    while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
}

int main()
{
    int n,ans=0; in(n);
    for(rg int l=1,r,len;l<=n;l=r+1) {
        r=n/(n/l),len=r-l+1;
        ans+=n/l*len;
    }
    printf("%d\n",ans);
}

第二題也是轉換一下題目要求的東西

\[a\mod b= a-\lfloor\frac{a}{b}\rfloor\times b \]

然后套一下等比數列求和就可以了
注意一下邊界

Code

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define rg register
#define lol long long
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)?(b)?(a):(b)

using namespace std;

void in(lol &ans) {
    ans=0; char i=getchar();
    while(i<'0' || i>'9') i=getchar();
    while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
}

int main()
{
    lol n,m;in(n),in(m); lol ans=n*m;
    for(rg lol l=1,r,len;l<=n;l=r+1) {
        if(m/l!=0) r=Min(m/(m/l),n);
        else r=n; len=(r-l+1);
        ans-=(m/l)*len*(l+r)/2;
    }
    printf("%lld\n",ans);
}

第三題題解

下面是配合莫比烏斯反演的題
[POI2007]ZAP-Queries 題解1
[SDOI2015]約數個數和 題解2
YY的GCD 題解3

博主蒟蒻,隨意轉載.但必須附上原文鏈接

http://www.cnblogs.com/real-l/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM