The sol to Bismuth / Linear Sieve

Qian·JXのjoker發表於2024-11-17

The sol to Bismuth / Linear Sieve

https://www.luogu.com.cn/problem/P11169

思路

因為懶惰,所以直接轉載了當時參考的這篇部落格

https://www.luogu.com.cn/article/ys9ualoj

首先觀察樣例發現第一個樣例一定是 \(\lceil \frac{n}{2} \rceil\)

手推一下加入數字的過程:

當處理到數字二時,此時 \(cntp = 1, counter = 1\),並將 \(isnotprime_{4}\) 賦值為 \(1\)

當處理到數字三時,此時 \(cntp = 2, counter = 2\),並將 \(isnotprime_{6}\) 賦值為 \(1\)

......

首先大於所有大於 \(1\) 的奇數而言更新其他數字是否被篩到時,則必然列舉到 \(2\) 就停止了。

接著對於所有大於 \(0\) 的偶數而言更新其他數字是否被篩到時,由於本身是偶數,所以其篩出的數也必然是偶數。

由於兩種篩法都沒有辦法篩出奇數,而 \(n\) 以內大於 \(1\) 的奇數有 \(\lceil \frac{n - 2}{2} \rceil\) 個,接著 \(2\) 一開始沒有被篩到,所以 \(cntp\) 一定為 \(\lceil \frac{n - 2}{2} \rceil + 1 = \lceil \frac{n}{2} \rceil\)

接著考慮計算 \(counter\) 的值,對於每個未被篩到的元素單獨考慮貢獻,假設 \(x\) 為篩倍數時篩到當前考慮的元素中某個 \(i\),當前考慮元素為 \(y\)\(l\) 為未被篩到的元素中小於等於 \(y\)\(\operatorname{lcm}\)

首先必然有 \(x \times y \le n\),那麼現在 \(x\) 的範圍在 \([1, \lfloor \frac{n}{2} \rfloor]\) 之內,那麼 \(x\) 整除 \(l\),由於 \(l\) 增長速度較快,所以需要考慮的元素數量較少,那麼只需要考慮這些 \(l \le n\) 中未被篩到的元素。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
int gcd(int a,int b){
    return __gcd(a,b);
}
int lcm(int a,int b){
    return a/gcd(a,b)*b;
}
signed main(){
    freopen("Bismuth.in","r",stdin);
    freopen("Bismuth.out","w",stdout);
    int n;
    cin>>n;
    if(n==1){
        cout<<"0 0"<<endl;return 0;
    }
    cout<<((n+1)>>1)<<" ";
    int l=2;
    int ans=n/2/2;
    for(int i=2;i<n/2;i++){
        int nw=2*i-1;
        l=lcm(l,nw);
        if(l>n) break;
        ans+=(n/nw)/l;
    }
    cout<<ans<<endl;
    return 0;
}

水完了。

相關文章