JZOJ4872. 太阳神

题目大意

给定一个 n ,求有多少对(a,b)满足 an,bn,lcm(a,b)>n

Data Constraint
n1010

题解

直接计算不太好算。考虑用所有 n2 的方案减去不合法的方案。
现在要求 ni=1nj=1[i×j(i,j)n]
d=(i,j)
易得 nd=1ni=1nj=1[(i,j)=1][i×j×dn]
莫比乌斯反演一波: nd=1nk=1μ(k)ni=1nj=1[i×j×dnk2]
转换主体: nk=1μ(k)nd=1ni=1nj=1[i×j×dnk2]
前面是根号的,现在要求后面那一部分,也就是求 a=1b=1c=1abcn
分类讨论即可。假设 abc ,那么 a[1,n13] b[1,na] ,暴力枚举 a,b 统计即可。通过积分可以算出,这个部分的复杂度是 O(n16)

时间复杂度: O(n23)

SRC

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std ;

#define N 100000 + 10
typedef long long ll ;
const int MO = 1e9 + 7 ;

bool flag[N] ;
int Pri[N] , miu[N] ;
ll n , ans ;

void Pre() {
    miu[1] = 1 ;
    for (int i = 2 ; i < N ; i ++ ) {
        if ( !flag[i] ) {
            Pri[++Pri[0]] = i ;
            miu[i] = -1 ;
        }
        for (int j = 1 ; j <= Pri[0] ; j ++ ) {
            if ( i * Pri[j] >= N ) break ;
            flag[i*Pri[j]] = 1 ;
            if ( i % Pri[j] == 0 ) { miu[i*Pri[j]] = 0 ; break ; }
            else miu[i*Pri[j]] = -miu[i] ;
        }
    }
}

ll Solve( ll c ) {
    ll ret = 0 ;
    for (int a = 1 ; (ll)a * a * a <= c ; a ++ ) {
        ret = (ret + 3ll * (c / a / a - a) % MO + 1ll) % MO ;
        int UP = sqrt( c / a ) ;
        for (int b = a + 1 ; b <= UP ; b ++ ) {
            ret = (ret + 6ll * (c / a / b - b) % MO + 3ll) % MO ;
        }
    }
    return ret ;
}

int main() {
    freopen( "ra.in" , "r" , stdin ) ;
    freopen( "ra.out" , "w" , stdout ) ;
    Pre() ;
    scanf( "%lld" , &n ) ;
    ans = 0 ;
    int UP = sqrt(n) ;
    for (int i = 1 ; i <= UP ; i ++ ) {
        ans = (ans + (ll)miu[i] * Solve( n / i / i ) % MO + MO) % MO ;
    }
    n %= MO ;
    ans = (n * n % MO - ans + MO) % MO ;
    printf( "%lld\n" , ans ) ;
    return 0 ;
}

以上.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值