• 解方程【狄利克雷卷积+莫比乌斯反演+积性函数】


    题意

    数列 (f(i)) 使得对任意的 (n) 都有:

    [sum_{i|n}{f(i) imes sigma_p(frac{n}{i})}=sigma_q(n) ]

    其中,(sigma_k(n)) 表示 (n) 的约数的 (k) 次方和。求出 (f_imod 998244353 (1leq i leq n)) 的异或和。

    (1leq n,p,q leq 10^7,且不保证 pleq q)

    题目链接:https://ac.nowcoder.com/acm/contest/7329/F

    分析

    观察等式的左边,可以发现很符合狄利克雷卷积的形式,即:((f*sigma_p)(n)=sigma_q(n))

    同时,发现:(sigma_k=Id_k*I),可以得到:((f*Id_p)(n)=Id_k(n)),即:

    [sum_{i|n}{f(i) imes frac{n^p}{i^p}}=n^q ]

    化简得:

    [sum_{i|n}{frac{f(i)}{i^p}}=n^{q-p} ]

    (F(n)=n^{q-p},g(n)=frac{f(n)}{n^p}),可以发现 (F(n)) 得求解很容易,而 (g(n)) 得求解较难(这不是刚好满足莫比乌斯反演吗)。根据莫比乌斯反演的约数形式:

    [F(n)=sum_{d|n}f(d)Longrightarrow f(n)=sum_{d|n}{mu(d) imes F(frac{n}{d})} ]

    可得:

    [g(n)=frac{f(n)}{n^q}=sum_{d|n}{frac{mu(d)}{d^{q-p}}} ]

    显然,(g(n)) 是一个积性函数,可以用线性筛处理,关键是如何求出 (n) 为质数和 (i\% prime[j])(i*prime[j])(g) 的函数值。

    • (n) 为质数时,代入易得 (g(n)=1-frac{1}{n^{q-p}})

    • (i\% prime[j]==0) 时,有 (g(i*prime[j])=g(i))

    • (i\% prime[j] eq 0) 时,根据积性函数,有 (g(i*prime[j])=g(i)*g(prime[j]))

    对于 (n^q) ,由于数据比较大,因此要尽量减少使用快速幂的次数。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int N=1e7+7;
    const int mod=998244353;
    int n,p,q;
    bool vis[N];
    int prime[N],tol,f[N];
    ll num[N];
    ll power(ll a,ll b)
    {
        ll res=1;
        a%=mod;
        while(b)
        {
            if(b&1) res=res*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return res;
    }
    int solve()
    {
        int ans=0,tol=0;
        f[1]=1;
        num[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(!vis[i])
            {
                prime[++tol]=i;
                if(q<=p) f[i]=(1-power(i,p-q)+mod)%mod;
                else f[i]=(1-power(i,1LL*(q-p)*(mod-2))+mod)%mod;
                num[i]=power(i,q);
            }
            for(int j=1;j<=tol&&i*prime[j]<=n;j++)
            {
                vis[i*prime[j]]=1;
                num[i*prime[j]]=num[i]*num[prime[j]]%mod;
                if(i%prime[j]==0)
                {
                    f[i*prime[j]]=f[i];
                    break;
                }
                else
                    f[i*prime[j]]=1LL*f[i]*f[prime[j]]%mod;
            }
        }
        for(int i=1;i<=n;i++)
            ans^=(1LL*f[i]*num[i]%mod);
        return ans;
    }
    int main()
    {
        scanf("%d%d%d",&n,&p,&q);
        printf("%d
    ",solve());
        return 0;
    }
    
  • 相关阅读:
    常见的HTTP状态码(HTTP Status Code)说明
    eclipse tomcat maven热部署
    log4j.properties 详解与配置步骤
    js玩命加载……
    git学习
    vim学习笔记
    Android中在不同activity中进行自定义广播的解析
    Android中本地广播的实现
    Android中自定义广播的实现
    Android中获得网络状况的实现
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13759097.html
Copyright © 2020-2023  润新知