LibreOJ - 6053(积性函数前缀和,pn筛角度)

题意:
在这里插入图片描述
n<=1e10
思路: 积性函数性质,pn筛角度
易知f(i)是积性函数。
f = g ∗ h , 其中 ∗ 表示狄利克雷卷积 f = g*h,其中*表示狄利克雷卷积 f=gh,其中表示狄利克雷卷积
试着构造一下h和g,由于 f ( p ) = { p − 1 = φ ( p ) , p > 2 p + 1 , p = 2 f(p)=\begin{cases}p-1=\varphi(p)&,p>2\\p+1&,p=2\end{cases} f(p)={p1=φ(p)p+1,p>2,p=2
考虑p=2时,f固定有f(2^k)的贡献,构造 g ( x ) = { φ ( x ) , x ∤ 2 3 φ ( x ) , x ∣ 2 g(x)=\begin{cases}\varphi(x)&,x\nmid2\\3\varphi(x)&,x\mid2\end{cases} g(x)={φ(x)3φ(x),x2,x2
由积性函数定义,有 f ( p ) = h ( p ) g ( 1 ) + h ( 1 ) g ( h ) 和 f ( 1 ) = h ( 1 ) g ( 1 ) , 而 h ( p ) = f ( p ) , 所以 h ( p ) = 0 , h ( 1 ) = 1 f(p)=h(p)g(1)+h(1)g(h)和f(1)=h(1)g(1),而h(p)=f(p),所以h(p)=0,h(1)=1 f(p)=h(p)g(1)+h(1)g(h)f(1)=h(1)g(1),h(p)=f(p),所以h(p)=0,h(1)=1
也就是说h(x)只可能在x为powerful number时取到非零数,而pn数量级是 n \sqrt{n} n 的,考虑pn筛。
∑ i = 1 n f ( i ) = ∑ i = 1 n h ( i ) ∑ j = 1 ⌊ n i ⌋ g ( j ) \sum_{i=1}^nf(i)=\sum_{i=1}^nh(i)\sum_{j=1}^{{\lfloor\frac{n}{i}\rfloor}}g(j) i=1nf(i)=i=1nh(i)j=1ing(j)
接下来是g(i)的前缀和如何快速求
∑ i = 1 n g ( i ) = ∑ i = 1 n φ ( i ) + 2 ∑ i = 1 ⌊ n 2 ⌋ φ ( 2 i ) \sum_{i=1}^ng(i) =\sum_{i=1}^n\varphi(i)+2\sum_{i=1}^{\lfloor\frac{n}{2}\rfloor}\varphi(2i) i=1ng(i)=i=1nφ(i)+2i=12nφ(2i),前半部分用杜教筛可以在 O ( n 2 3 ) 解决。 O(n^{\frac{2}{3}})解决。 O(n32)解决。
现在解决后面的求和问题,我们设 S ( n ) = ∑ i = 1 n φ ( 2 i ) S(n)=\sum_{i=1}^n\varphi(2i) S(n)=i=1nφ(2i)
利用积性函数性质并且尽量往前缀和上靠
当n为偶数时,考虑把 φ ( 2 i ) 的 i 分为奇数和偶数两部分求和 \varphi(2i)的i分为奇数和偶数两部分求和 φ(2i)i分为奇数和偶数两部分求和
S ( n ) = ∑ i = 1 n 2 ( φ ( 2 i ) + φ ( 2 ( n + i ) ) = ∑ i = 1 n 2 ( φ ( 2 ( 2 i − 1 ) ) + φ ( 2 ∗ 2 i ) ) = ∑ i = 1 n 2 ( φ ( 2 i − 1 ) + 2 φ ( 2 i ) ) = ∑ i = 1 n 2 ( φ ( 2 i − 1 ) + φ ( 2 i ) ) + ∑ i = 1 n 2 φ ( 2 i ) = ∑ i = 1 n φ ( i ) + S ( n 2 ) S(n)=\sum_{i=1}^{\frac{n}{2}}{(\varphi(2i)+\varphi(2(n+i))}\\=\sum_{i=1}^{\frac{n}{2}}{(\varphi(2(2i-1))+\varphi(2*2i))}\\=\sum_{i=1}^{\frac{n}{2}}{(\varphi(2i-1)+2\varphi(2i))}\\=\sum_{i=1}^{\frac{n}{2}}{(\varphi(2i-1)+\varphi(2i))}+\sum_{i=1}^{\frac{n}{2}}\varphi(2i)\\=\sum_{i=1}^n\varphi(i)+S(\frac{n}{2}) S(n)=i=12n(φ(2i)+φ(2(n+i))=i=12n(φ(2(2i1))+φ(22i))=i=12n(φ(2i1)+2φ(2i))=i=12n(φ(2i1)+φ(2i))+i=12nφ(2i)=i=1nφ(i)+S(2n)
当n为奇数时,考虑往上面的式子转化
S ( n ) = S ( n − 1 ) + φ ( 2 n ) S(n)=S(n-1)+\varphi(2n) S(n)=S(n1)+φ(2n),而S(n-1)上面已经推出来了
继续化简
S ( n ) = S ( n − 1 2 ) + ∑ i = 1 n − 1 φ ( i ) + φ ( 2 n ) = S ( n − 1 2 ) + ∑ i = 1 n − 1 φ ( i ) + φ ( n ) ( 2 和 n 互质 ) = S ( n − 1 2 ) + ∑ i = 1 n φ ( i ) S(n)=S(\frac{n-1}{2})+\sum_{i=1}^{n-1}\varphi(i)+\varphi(2n)\\=S(\frac{n-1}{2})+\sum_{i=1}^{n-1}\varphi(i)+\varphi(n)(2和n互质)\\=S(\frac{n-1}{2})+\sum_{i=1}^{n}\varphi(i) S(n)=S(2n1)+i=1n1φ(i)+φ(2n)=S(2n1)+i=1n1φ(i)+φ(n)(2n互质)=S(2n1)+i=1nφ(i)
综上:
S ( n ) = S ( ⌊ n 2 ⌋ ) + ∑ i = 1 n φ ( i ) S(n)=S(\lfloor\frac{n}{2}\rfloor)+\sum_{i=1}^{n}\varphi(i) S(n)=S(⌊2n⌋)+i=1nφ(i)
于是可以递归求解了,最多logn层
所以g(i)的前缀和问题解决了,即
∑ i = 1 n g ( i ) = ∑ i = 1 n φ ( i ) + 2 S ( n 2 ) \sum_{i=1}^ng(i)=\sum_{i=1}^n\varphi(i)+2S(\frac{n}{2}) i=1ng(i)=i=1nφ(i)+2S(2n)

现在解决h(x),我们只关心每个 h ( p k ) ,其中 k > 1 h(p^k),其中k>1 h(pk),其中k>1,因为h(x)是积性函数,其他pn数可以由此组合出来。
考虑 f ( p k ) = ∑ i + j = k , 0 < = i < = k h ( p i ) g ( p j ) , 其中 g ( p j ) = p j − 1 ( p − 1 ) f(p^k)=\sum_{i+j=k,0<=i<=k}h(p^i)g(p^j),其中g(p^j)=p^{j-1}(p-1) f(pk)=i+j=k,0<=i<=kh(pi)g(pj),其中g(pj)=pj1(p1),且g(1)=1
h ( p k ) = f ( p k ) − ∑ i + j = k , 0 < = i < = k − 1 h ( p i ) g ( p j ) h(p^k)=f(p^k)-\sum_{i+j=k,0<=i<=k-1}h(p^i)g(p^j) h(pk)=f(pk)i+j=k,0<=i<=k1h(pi)g(pj)暴力算即可,不超过logn项。
而h(x)有值的地方不超过 n \sqrt{n} n ,这部分复杂度 n l o g n \sqrt{n}logn n logn,复杂度瓶颈应该在杜教筛 O ( n 2 / 3 ) O(n^{2/3}) O(n2/3)那。

PS:多观察函数性质,特别是积性函数,和已知的一些数论函数的性质或者数论函数本身的定义。多往前面已求出来的问题上思考转化。
会爆longlong,博主直接用int128了。

const int N=1e6+5;
const int mod=1e9+7;
const double eps=1e-8;
int ans,n,limit,sq;
int p[80001], tot,h[N][41],eu[N],SUM[N],S1[N];
bool v[N];
int ni[51],gg[51];
map<int, int >mpS1,mpeu;
int read(){
    ll x = 0 ,f = 1;
    char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch)){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
void print(ll x){
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) print(x/10);
    putchar(x % 10 + '0');
}
int qsm(int a, int b){
    a%=mod;
    int ans = 1, temp = a;
    while (b){
        if (b & 1) ans = ans*temp%mod;
        temp = temp*temp%mod;
        b >>= 1;
    }
    return ans;
}
void ini(){//有关全局n的预处理,h(p^k)的预处理(k>1)
    for(sq=1;p[sq]*p[sq]<=n&&sq+1<=tot ;sq++);
     _for(i,1,sq){
        gg[0] = 1;
        if( p[i]==2 ) gg[1] = 3;
        else gg[1] = eu[p[i]]%mod;
        h[i][0] = 1;
        h[i][1] = 0;
        for(int j=p[i]*p[i],e=2;j<=n;j*=p[i],e++){
            gg[e] = gg[e-1]%mod*p[i]%mod;
            h[i][e] = (p[i]^e)%mod;
            for(int k=0 ;k<e ;k++){
                h[i][e] = (h[i][e] - h[i][k]*gg[e-k]%mod+mod)%mod;
            }
        }
    }
}
void shai(int n){
    _for(i,1,41) ni[i] = qsm(i,mod-2);
    v[1] = eu[1] = 1;
    _for(i, 2, n){
        if (!v[i]){
            p[++tot] = i;
            eu[i] = i - 1;
        }
        _for(j, 1, tot){
            if (i * p[j] > n) break;
            v[i * p[j]] = 1;
            if (i % p[j] == 0){
                eu[i * p[j]] = eu[i] * p[j];
                break;
            }
            eu[i * p[j]] = eu[i] * (p[j] - 1);
        }
    }
    _for(i, 1, n) {
        SUM[i] = (eu[i]%mod + SUM[i-1])%mod;
    }
}
int geteu(int x){
    if (x <= 1e6) return SUM[x];
    if (mpeu[x]) return mpeu[x];
    int ans = x %mod* (x + 1)%mod %mod*ni[2]%mod;
    for (int l = 2, r = 0; l <= x; l = r + 1){
        r = x / (x / l);
        ans -= (r - l + 1)%mod * geteu(x / l)%mod;
        ans += mod;
        ans %= mod;
    }
    return mpeu[x] = ans;
}
int get_sum(int x){
    if( !x ) return 0;
    if (mpS1[x]) return mpS1[x];
    if (x==1) return mpS1[x] = 1;
    return mpS1[x] = (get_sum(x/2) + geteu(x))%mod;
}
void dfs(int cur,int val,int num){//累计到第num-1个质数的乘积为cur,h(cur) = val
    ans = (ans + val*(geteu(n/cur)+get_sum(n/cur/2)*2%mod)%mod)%mod;
    for(int i=num ;i<=sq ;i++){
        if( p[i] * p[i] > n/cur ) break;
        for(int t=p[i]*p[i] ,e=2; cur*t<=n ;t *= p[i],e++){
            dfs(cur*t,val*h[i][e]%mod,i+1);
        }        
    }
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif  
    // IOS;
    shai(1e6);
    // cin>>n;
    n = read();
    ini();
    dfs(1,1,1);
    print(ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值