【XSY2721】求和 杜教筛

题目描述

  设\(n=\prod a_i^{p_i}\),那么定义\(f_d(n)=\prod{(-1)^{p_i}[p_i\leq d]}\)。特别的,\(f_1(n)=\mu(n)\)。

  给你\(n,k\),求
\[
\sum_{i=1}^n\sum_{j=1}^n\sum_{d=1}^kf_d(\gcd(i,j))
\]
  \(n\leq {10}^{10},k\leq 40\)

题解

  先做一些简单的处理
\[
\begin{align}
ans&=\sum_{i=1}^n\sum_{j=1}^n\sum_{d=1}^kf_d(\gcd(i,j))\&=\sum_{i=1}^n\sum_{d=1}^kf_d(i)(2(\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}\varphi(j))-1)
\end{align}
\]
  后面\(\varphi\)用杜教筛可以在\(O(n^\frac{2}{3})\)内搞出来。

  设\(\lambda(n)=f_\infty(n)=\prod{(-1)}^{p_i}\)

  考虑容斥,有:
\[
f_d(n)=\lambda(n)\sum_{i^d|n}\mu(i)
\]

\[
\begin{align}
F_d(n)&=\sum_{i=1}^nf_d(i)\&=\sum_{i=1}^n\lambda(i)\sum_{j^d|i}\mu(j)\&=\sum_{i=1}^n\mu(i)\sum_{j=1}^{\lfloor\frac{n}{i^{d+1}}\rfloor}\lambda(i^{d+1}j)\&=\sum_{i=1}^{\lfloor\sqrt[d+1]{n}\rfloor}\lambda^{d+1}(i)\mu(i)\Lambda(\lfloor\frac{n}{i^{d+1}}\rfloor)
\end{align}
\]
  \(n\leq {10}^7\)的部分预处理,其他的每次枚举。这部分每次枚举是\(\sqrt{n}\)的。总的是\(O(n^\frac{2}{3})\)的。(和杜教筛的分析方法一样。)
\[
\begin{align}
\sum_{j|i}\lambda(j)&=[i是完全平方数]\\sum_{i=1}^n\sum_{j|i}\lambda(j)&=\sqrt{n}\\sqrt{n}=\sum_{i=1}^n\sum_{j}[j|i]\lambda(i)&=\sum_{\frac{i}{j}=1}^n\sum_{j=1}^{\lfloor\frac{n}{\frac{i}{j}}\rfloor}\lambda(j)
=\sum_{i=1}^n\Lambda(\lfloor\frac{n}{i}\rfloor)\\Lambda(n)&=\sqrt {n}-\sum_{i=2}^n\Lambda(\lfloor\frac{n}{i}\rfloor)
\end{align}
\]
  后面\(\Lambda(n)\)用杜教筛可以在\(O(n^\frac{2}{3})\)内搞出来

  反正总的是\(O(n^\frac{2}{3})\)的就对了。。。

  时间复杂度:\(O(n^\frac{2}{3})\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int getsqrt(ll n)
{
    int l=1,r=1000000;
    while(l<r)
    {
        int mid=(l+r+1)>>1;
        if((ll)mid*mid>n)
            r=mid-1;
        else
            l=mid;
    }
    return l;
}
ll n;
ll _sqrt;
namespace hashset
{
    int getnum(ll x)
    {
        return n/x;
    }
}
using hashset::getnum;
int miu[10000010];
int phi[10000010];
int c[10000010];
int cs[10000010];
const int maxn=10000000;
int b[10000010];
int pri[1000010];
int cnt;
int d[10000010];
int e[10000010];
int f[10000010];
int k;
int vis[10000010];
int qp[10000010];
int qc[10000010];
void init()
{
    c[1]=phi[1]=miu[1]=f[1]=e[1]=1;
    d[1]=f[1]=0;
    int i,j;
    for(i=2;i<=maxn;i++)
    {
        if(!b[i])
        {
            miu[i]=-1;
            phi[i]=i-1;
            c[i]=-1;
            pri[++cnt]=i;
            d[i]=e[i]=1;
            f[i]=1;
        }
        for(j=1;j<=cnt&&i*pri[j]<=maxn;j++)
        {
            b[i*pri[j]]=1;
            c[i*pri[j]]=-c[i];
            f[i*pri[j]]=f[i]+1;
            if(i%pri[j]==0)
            {
                miu[i*pri[j]]=0;
                phi[i*pri[j]]=phi[i]*pri[j];
                d[i*pri[j]]=d[i]+1;
                e[i*pri[j]]=max(d[i*pri[j]],e[i]);
                break;
            }
            d[i*pri[j]]=1;
            e[i*pri[j]]=e[i];
            miu[i*pri[j]]=-miu[i];
            phi[i*pri[j]]=phi[i]*phi[pri[j]];
        }
    }
    for(i=1;i<=maxn;i++)
    {
        if(e[i]>k)
            f[i]=0;
        else
            f[i]=(f[i]&1?-1:1)*(k-e[i]+1);
        f[i]+=f[i-1];
//      miu[i]+=miu[i-1];
        phi[i]+=phi[i-1];
        cs[i]=cs[i-1]+c[i];
    }
}
int getphi(ll n)
{
    if(n<=maxn)
        return phi[n];
    int x=getnum(n);
    if(vis[x]&1)
        return qp[x];
    vis[x]|=1;
    ll i,j;
    int s=n*(n+1)>>1;
    for(i=2;i<=n;i=j+1)
    {
        j=n/(n/i);
        s-=(j-i+1)*getphi(n/i);
    }
    qp[x]=s;
    return s;
}
int getc(ll n)
{
    if(n<=maxn)
        return cs[n];
    int x=getnum(n);
    if(vis[x]&2)
        return qc[x];
    vis[x]|=2;
    int s=getsqrt(n);
    ll i,j;
    for(i=2;i<=n;i=j+1)
    {
        j=n/(n/i);
        s-=(j-i+1)*getc(n/i);
    }
    qc[x]=s;
    return s;
}
ll pw[1000010];
int pw2[1000010];
int pw3[1000010];
int getfd(ll n)
{
    if(n<=maxn)
        return f[n];
    int i,j;
    for(i=1;(ll)i*i<=n;i++)
    {
        pw[i]=i;
        pw2[i]=pw3[i]=c[i];
    }
    int m=i-1;
    int s=0;
    for(j=1;j<=k;j++)
    {
        for(i=1;i<=m;i++)
        {
            pw[i]*=i;
            if(pw[i]>n)
                break;
            pw2[i]*=pw3[i];
            s+=miu[i]*pw2[i]*getc(n/pw[i]);
        }
    }
    return s;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
#endif
    scanf("%lld%d",&n,&k);
    _sqrt=getsqrt(n);
    init();
    int s=0;
    ll i,j;
    int now,last=0;
    int ans=0;
    for(i=1;i<=n;i=j+1)
    {
        j=n/(n/i);
        now=getfd(j);
        ans+=(now-last)*(2*getphi(n/i)-1);
        last=now;
    }
    ans&=(1<<30)-1;
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/ywwyww/p/8513546.html

时间: 2024-11-09 00:40:52

【XSY2721】求和 杜教筛的相关文章

BZOJ4805: 欧拉函数求和(杜教筛)

4805: 欧拉函数求和 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 614  Solved: 342[Submit][Status][Discuss] Description 给出一个数字N,求sigma(phi(i)),1<=i<=N Input 正整数N.N<=2*10^9 Output 输出答案. Sample Input 10 Sample Output 32 HINT Source By FancyCoder 直接大力杜教筛

【BZOJ3944/4805】Sum/欧拉函数求和 杜教筛

[BZOJ3944]Sum Description Input 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问 Output 一共T行,每行两个用空格分隔的数ans1,ans2 Sample Input 6 1 2 8 13 30 2333 Sample Output 1 1 2 0 22 -2 58 -3 278 -3 1655470 2 题解: 粘自http://blog.csdn.net/skywalkert/article/details/

【BZOJ4805】欧拉函数求和(杜教筛)

[BZOJ4805]欧拉函数求和(杜教筛) 题面 BZOJ 题解 好久没写过了 正好看见了顺手切一下 令\[S(n)=\sum_{i=1}^n\varphi(i)\] 设存在的某个积性函数\(g(x)\) \[(g*\varphi)(i)=\sum_{d|i}g(d)\varphi(\frac{i}{d})\] \[\sum_{i=1}^n(g*\varphi(i))(i)\] \[=\sum_{i=1}^n\sum_{d|i}g(d)\varphi(\frac{i}{d})\] \[=\sum

杜教筛 学习总结

看了看唐老师的blog,照猫画虎的做了几道题目,感觉对杜教筛有些感觉了 但是稍微有一点难度的题目还是做不出来,放假的时候争取都A掉(挖坑ing) 这篇文章以后等我A掉那些题目之后再UPD上去就好啦 由于懒得去写怎么用编辑器写公式,所以公式就准备直接copy唐老师的啦 首先积性函数和完全积性函数什么的就不再多说了 列举常见的积性函数: 1.约数个数函数和约数个数和函数 2.欧拉函数phi 3.莫比乌斯函数mu 4.元函数e 其中e(n)=[n==1] 5.恒等函数I 其中I(n)=1 6.单位函数

【学术篇】分析矿洞 杜教筛

数论什么的都去死吧! 看着题解我都能化式子用完4页草纸... 另外吐槽一句出题人的拼音学的是真好, 不知道是不是故意的. 其实题解已经写得挺详细的了. 我就是提一些出题人觉得太easy没必要提但是做题还是需要的一些东西....(因为这些东西我基本都是现学的) 然而之前刚刚学完mobius反演就暂时性脱坑的我啥也不会啊.. 看到前排dp和曲神在水luogu的欢(bao/du)乐(ling/liu)赛, 就想去看看. 然后就点了报名但是发现自己什么都不会. 去看了看T1. 就是这道题. 然后成功的化

P4213 【模板】杜教筛(Sum)

\(\color{#0066ff}{题 目 描 述}\) 给定一个正整数\(N(N\le2^{31}-1)\) 求 \(\begin{aligned} ans_1=\sum_{i=1}^n\varphi(i) \end{aligned}\) \(\begin{aligned} ans_2=\sum_{i=1}^n \mu(i) \end{aligned}\) \(\color{#0066ff}{输 入 格 式}\) 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N

51nod 1220 约数之和(杜教筛 + 推推推推推公式)

题意 给出\(n(1\leq n \leq 10^9)\),求\(\sum_{i=1}^n\sum_{j=1}^n\sigma(ij)\),其中\(\sigma(n)\)表示\(n\)的约数之和. balabala 交了两道杜教筛的的板子题(51nod 1239, 1244)就看到了这题,然后不会搞,然后看题解看了一天一夜终于彻底搞明白一发A掉了...感觉学到了很多,写个博客整理一下,如有错请指出. 技能需求 数论函数与线性筛 莫比乌斯反演(也可以当成容斥去理解) 狄利克雷卷积 杜教筛 强大的数

【数论】狄利克雷卷积及其快速计算方法及杜教筛

目录(假的 狄利克雷卷积基础知识 数论函数 狄利克雷卷积定义 狄利克雷卷积性质 常用卷积 卷积计算方法 最暴力的暴力 稍好的暴力 优美的暴力 莫比乌斯反演(待填坑) 杜教筛 经典杜教筛 第二种杜教筛 第三种杜教筛 背景 本人即将去CTS&APIO2019,由于一些特殊原因,发现自己数论突然变得很菜. 就决定在去的前一天,翻出来以前的数论学习资料看一看.翻到了czgj的校内狄利克雷卷积课件,发现其中提到了的任意数列\(f(n)\)和\(g(n)\)的狄利克雷卷积\((f*g)(n)\)(从1到n,

[51nod1227]平均最小公倍数(莫比乌斯反演+杜教筛)

题意 求 $\sum_{i=a}^b \sum_{j=1}^i \frac{lcm(i,j)}{i}$. 分析 只需要求出前缀和, $$\begin{aligned}\sum_{i=1}^n \sum_{j=1}^i \frac{lcm(i,j)}{i} &= \sum_{i=1}^n \sum_{j=1}^i \frac{j}{gcd(i,j)} \\&= \sum_{d=1}^n \sum _{i=1}^n \sum_{j=1}^i \frac{j}{d} \cdot [gcd(i,j