杜教筛

重新学习了杜教筛,发现其实理解起来很容易,应该是课件做的好
全文以大写为相应小写的前缀和

杜教筛的一般步骤

设需求解 \(F(n)=\sum_{i=1}^nf(i)\)
找到一个函数 \(g(x)\) ,要求 \(g(x)\) 的前缀和很容易计算,
并且使得 \(\sum_{d|n}f(d)g(\frac{n}{d}) = h(n)\)
\(h(n)\) 也很容易计算
那么就有 \(g(1)F(n)=H(n) - \sum_{i=2}^n g(i)F(\lfloor \frac{n}{i} \rfloor)\)


做了这么几个题

1.莫比乌斯函数之和
\(\mu * 1\) 就很好求了,1和 \(e\) 的前缀和都是\(O(1)\)

2.欧拉函数之和
\(\varphi * 1\) 就好了,因为 \(\varphi * 1 = id\)

3.hdu5608
其实就是给你卷好了让你求,就 \(nlogn\) 算一部分再每次 \(\sqrt{n}\) 一下

4.最大公约数之和
\(a(x)=\sum_{i=1}^x gcd(x,i)\) 那么答案就是 \(2*A(n)-\sum_{i=1}^n i\)
发现 \(a(n)=\sum_{i=1}^n gcd(i,n)=\sum_{d|n}d\varphi(\dfrac{n}{d})\)

\(A(n)=\sum_{i=1}^n \sum_{d|i}\varphi(d)\dfrac{i}{d}\)
\(=\sum_{i=1}^n \varphi(i) \sum_{j=1}^{\lfloor \frac{n}{i}\rfloor} j\)
\(=\sum_{i=1}^n \varphi(i) \frac{\lfloor \frac{n}{i}\rfloor(\lfloor \frac{n}{i}\rfloor+1)}{2}\)
然后就可以强行根号套求 \(\varphi\) ,这样复杂度是对的是因为杜教筛是记忆化得,求一次基本上都求了

发一个 \(\varphi\)\(\mu\) 的代码

const int N=1000000;
bool np[N];
int p[N],tot,mu[N];
ll phi[N];
void init(){
    np[1]=1,phi[1]=1,mu[1]=1;
    For(i,2,N){
        if(!np[i])p[++tot]=i,phi[i]=i-1,mu[i]=-1;
        for(int j=1;j<=tot&&i*p[j]<N;j++){
            np[i*p[j]]=1;
            if(i%p[j]){
                phi[i*p[j]]=phi[i]*(p[j]-1);
                mu[i*p[j]]=-mu[i];
            }else{
                phi[i*p[j]]=phi[i]*(p[j]);
                mu[i*p[j]]=0;
                break;
            }
        }
    }
    For(i,2,N)phi[i]+=phi[i-1];
    For(i,2,N)mu[i]+=mu[i-1];
}
map<int,ll> f;
inline ll F(int n){
    if(n<N)return phi[n];
    else if(f.count(n))return f[n];
    ll ans=1ll*(n+1)*(n)/2;
    for(int i=2,j;i<=n;i=j+1){
        j=n/(n/i);
        ans-=(j-i+1)*F(n/i);
    }
    return f[n]=ans;
}
map<int,int> g;
inline int G(int n){
    if(n<N)return mu[n];
    else if(g.count(n))return g[n];
    int ans=1;
    for(int i=2,j;j<=n;i=j+1){
        j=n/(n/i);
        ans-=(j-i+1)*G(n/i);
    }
}
int main(){
    init();
    int l=rd(),r=rd();
    ll ans=F(r+1)-F(l)+G(r+1)-G(l);
}

转载于:https://www.cnblogs.com/flukehn/p/8111277.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值