牛客网-小A的数学题 【莫比乌斯反演】【迪利克雷卷积】

题目链接:https://ac.nowcoder.com/acm/contest/549/J

参考题解:https://www.cnblogs.com/henry-1202/p/10699252.html#_label7

 

反演后迪利克雷卷积,然后线性筛卷积,再分块处理。

预处理复杂度O(N) ,每次询问O(sqrt(N))。

并没有使用杜教筛继续优化。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6+100;
const int mod = 1e9+7;
int prime[N]; //素数表下标从1开始
bool mark[N]; //mark[i]==1表示i不是素数
ll F[N]; //要筛的积性函数
int tot;
int Low[N]; // Low[i]表示i的最小质因子的指数次幂,i=p1^a1+p2^a2+p3^a3.....,low[i]=p1^a1;
void get_list(int n){
    mark[1] = 1;
    F[1] = 1;
    Low[1] = 1;                                   //给出F[1]的值
    for(int i = 2;i <= n;i ++){
        if(!mark[i]) {
            Low[i] = i;
            prime[++tot] = i;
            F[i] = (1ll*i*i-1)%mod;                             //给出F[p]的值,p表示质数
        }
        for(int j = 1;j<=tot&&prime[j]*i<=n;j ++){  //prime[j]永远是被筛数的最小质因子,且一定小于等于i的最小质因子
            mark[i*prime[j]] = 1;
            if(!(i%prime[j])) {                     //i和prime[j]不互质的情况
                Low[i*prime[j]] = Low[i]*prime[j];
                if(Low[i]==i) F[i*prime[j]] = F[i]*prime[j]%mod*prime[j]%mod; //i中只包含prime[j]这一个质因子,此时给出F[p^x]的值
                else F[i*prime[j]] = F[i/Low[i]]*F[Low[i]*prime[j]]%mod;  //i中还包含其他质因子
                break;
            }
            Low[i*prime[j]] = prime[j];     //i和prime[j]互质的情况
            F[i*prime[j]] = F[i]*F[prime[j]]%mod;
        }
    }
    for(int i = 1; i <= n; i++) F[i] = (F[i-1]+F[i])%mod;
}
int main() {
    get_list(1e6);
    ll n,m;
    cin>>n>>m;
    if(n>m) swap(n,m);
    ll ans = 0;
    for(ll l=1,r;l<=n;l=r+1) {
        r=min(n/(n/l),m/(m/l));
        ans = (ans + (n/l)*(m/l)%mod*(F[r]-F[l-1]+mod)%mod)%mod;
    }
    cout<<ans;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值