BZOJ3561 DZY Loves Math VI 【Mobius Inversion】

topic

Given a positive integer n,m. beg

input format

A line of two integers n,m.

output format

An integer, the value of the answer modulo 1000000007.

input sample

5 4

Sample output

424

hint

Data size:

1<=n, m<=500000, there are 3 sets of data.

answer

Routine inversion:
\[ \begin{aligned} ans &= \sum\limits_{d = 1}^{n} d^{d} \sum\limits_{i = 1}^{\lfloor \frac{n} {d} \rfloor} \sum\limits_{j = 1}^{\lfloor \frac{m}{d} \rfloor} i^{d}j^{d} \qquad [gcd(i,j) = = 1] \\ &= \sum\limits_{d= 1}^{n} d^{d} \sum\limits_{k = 1}^{\lfloor \frac{n}{d} \rfloor} \ mu(k) k^{2d} \sum\limits_{i = 1}^{\lfloor \frac{n}{kd} \rfloor} i^{d} \sum\limits_{j = 1}^{\ lfloor \frac{m}{kd} \rfloor} j^{d} \end{aligned} \]
and then panicked, as if it couldn't go on.
Analyze the complexity carefully. For each \(d\) , inside That pile of stuff only needs \(O(\lfloor \frac{m}{d} \rfloor)\) to be calculated,
so the complexity is \(n\) times a harmonic series
, ie \(O(nlogn)\ )

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 500005,maxm = 100005,INF = 1000000000,P = 1e9 + 7;
int p[maxn],isn[maxn],pi,mu[maxn],n,m;
LL a[maxn],sum[maxn];
LL qpow(LL a,LL b){
    LL ans = 1;
    for (; b; b >>= 1, a = a * a % P)
        if (b & 1) ans = ans * a % P;
    return ans;
}
void init(){
    mu[1] = 1;
    for (int i = 2; i <= n; i++){
        if (!isn[i]) p[++pi] = i,mu[i] = -1;
        for (int j = 1; j <= pi && i * p[j] <= n; j++){
            isn[i * p[j]] = true;
            if (i % p[j] == 0){
                mu[i * p[j]] = 0;
                break;
            }
            mu[i * p[j]] = -mu[i];
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    if (n > m) swap(n,m);
    init();
    REP(i,m) a[i] = 1;
    LL ans = 0;
    for (int d = 1; d <= n; d++){
        for (LL i = 1; i <= m / d; i++){
            a[i] = a[i] * i % P;
            sum[i] = (sum[i - 1] + a[i]) % P;
        }
        LL tmp = 0;
        for (int k = 1; k <= n / d; k++){
            tmp = (tmp + (mu[k] * qpow(k,2 * d) % P + P) % P * sum[n / (k * d)] % P * sum[m / (k * d)] % P);
            tmp = (tmp + P) % P;
        }
        ans = (ans + qpow(d,d) * tmp % P) % P;
    }
    ans = (ans % P + P) % P;
    printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325102486&siteId=291194637