模拟赛t3 太阳神(ra) 题解

2022/6/6 23:21:48

本文主要是介绍模拟赛t3 太阳神(ra) 题解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

太阳神

求满足如下条件的数对$(a,b)$对数:$a,b$均为正整数且$a,b \leq n$而$lcm(a,b)>n$。

答案对$10^9+7$取模 $n\leq 10^{10}$.

原题题解写的看不懂

题意即为求

$\sum _{a=1} ^{N} \sum _{b=1} ^{N} [lcm(a,b)>N]$.

转化为

$N^2-\sum _{a=1} ^{N} \sum _{b=1} ^{N} [a*b/gcd(a,b) \leq N]$

把$a,b$最大公约数$d$提出来,化为

$N^2-\sum _{d=1}^{N}\sum _{a=1} ^{\lfloor \frac{N}{d} \rfloor} \sum _{b=1} ^{\lfloor \frac{N}{d} \rfloor} [a*b \leq \lfloor \frac{N}{d} \rfloor][gcd(a,b)==1]$

之后令

$f(x)=\sum _{a=1} ^{x} \sum _{b=1} ^{x} [a*b \leq x][gcd(a,b)==1]$

于是我们可以先枚举$\lfloor \frac{N}{d} \rfloor$,算出$\sum _{d=1} ^{N} f(\lfloor \frac{N}{d}\rfloor )$即可,由于$\lfloor \frac{N}{d} \rfloor$只有$\sqrt N$个,所以只需要利用数论分块枚举$\sqrt N$次即可!

接下来考虑如何快速求出$f(d)$

我们发现:

$f(d)=\sum _{a=1} ^{d} \sum _{b=1} ^{d} [a*b \leq d][gcd(a,b)==1]$

$=\sum _{a=1} ^{d-1} \sum _{b=1} ^{d-1} [a*b \leq d-1][gcd(a,b)==1]+\sum _{a=1} ^{d} \sum _{b=1} ^{d} [a*b==x][gcd(a,b)==1]$

$=f(d-1)+\sum _{a=1} ^{d} \sum _{b=1} ^{d} [a*b==x][gcd(a,b)==1]$

相当于把$x$质因数分解为$\prod p_i ^ {a_i}$,对于每个$p_i ^ {a_i}$,要么给$a$,要么给$b$,所以有$2^{sum[x]}$种方案,$sum[x]$即$x$的质数约数个数。

于是

$f(d)=f(d-1)+2^{sum[d]}$

$sum[x]$是可以线性筛的,于是我们就可以$O(N)$求$f(d)$了!

但是考虑到过于大的数据范围,我们考虑优化:

令$S(x)=\sum _{a=1} ^{x} \sum _{b=1} ^{x} [a*b \leq x]$

则有$f(x)=\sum _{a=1} ^{x} \sum _{b=1} ^{x} [a*b \leq x] - \sum _{t=2} ^{\sqrt x} \sum _{a=1} ^{x} \sum _{b=1} ^{x} [a*b \leq x][gcd(a,b)==t]$

$=S(x)-\sum _{t=2} ^{\sqrt x} \sum _{a=1} ^{\frac{x}{t^2}} \sum _{b=1} ^{\frac{x}{t^2}} [a*b \leq \frac{x}{t^2}][gcd(a,b)==1]$

$=S(x)-\sum _{t=2} ^{\sqrt x}f(\lfloor \frac{x}{t^2} \rfloor)$

这里面$S(x)$是可以数论分块$O(\sqrt x)$求得,于是我们可以递归来求$f(d)$了!别忘了加上记忆化,这里可以用$N/x$来记忆化。

我们在不爆空的情况下尽可能多筛一些$f(d)$,我这里就筛到了$10^7$.对于每一个$\lfloor \frac{N}{d} \rfloor$,时间复杂度就是$O(\sqrt {\frac{N}{d}})$.

计算一下总时间复杂度($log _{10^{10}} {10^7} = 0.7$):

$n^{0.7} \leq \frac{n}{d} \Rightarrow d \leq n^{0.3}$

于是有

$\displaystyle \int _1 ^{n^{0.3}} \sqrt {\frac{n}{x}}\,dx$ 

$=\sqrt n \displaystyle \int _1 ^{n^{0.3}} x^{-\frac{1}{2}}\,dx$

$=n^{\frac{1}{2}} 2x^{\frac{1}{2}}| _{1} ^{n^{0.3}}$

$= 2n^{0.5}(n^{0.15}-1)$

$\approx n^{0.65}$

所以时间复杂度为$O(n^{0.65})$

#define ll long long
#define chr 10000000
const int maxn=1e7+5;
int f[maxn],num[maxn],p[maxn/10],cnt=0;
bool vis[maxn];
ll N;
const int mod=1e9+7;
void gt(int n){
    for(int i=2;i<=n;i++){
        if(!vis[i]){
            p[++cnt]=i;
            num[i]=1;
        }
        for(int j=1;j<=cnt&&p[j]*i<=n;j++){
            vis[p[j]*i]=1;
            if(i%p[j]==0){
                num[p[j]*i]=num[i];
                break;
            }else num[p[j]*i]=num[i]+1;
        }
    }
    for(int i=1;i<=n;i++)
        f[i]=(f[i-1]+(1ll<<num[i]))%mod;
}
int F[maxn];
int f_(ll x){
    if(x<=chr) return f[x];
    if(~F[N/x]) return F[N/x];
    ll ans=0;
    for(ll i=1;i<=x;){
        ll j=x/(x/i);
        ans+=x/i*(1+j-i)%mod;
        ans%=mod;
        i=j+1;
    }
    for(ll i=2;i*i<=x;i++) (ans-=f_(x/(i*i)))%=mod;
    return F[N/x]=ans; 
}
int MAIN(){
    // file();
    cin>>N;gt(chr);memset(F,-1,sizeof F);
    ll ans=0;
    for(ll i=1;i<=N;"chr"){
        ll j=N/(N/i);
        (ans+=(ll)f_(N/i)*(j-i+1)%mod)%=mod;
        i=j+1;
    }
    N%=mod;
    cout<<((N*N-ans)%mod+mod)%mod<<endl;
    return 0;
}

 



这篇关于模拟赛t3 太阳神(ra) 题解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程