hdoj - 5608 function【杜教筛】+【莫比乌斯反演】

function

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1908    Accepted Submission(s): 678


 

Problem Description

There is a function f(x),which is defined on the natural numbers set N,satisfies the following eqaution

N2−3N+2=∑d|Nf(d)

calulate ∑Ni=1f(i)  mod 109+7.

 

 

Input

the first line contains a positive integer T,means the number of the test cases.

next T lines there is a number N


T≤500,N≤109

only 5 test cases has N>106.

 

 

Output

Tlines,each line contains a number,means the answer to the i-th test case.

 

 

Sample Input

 

1 3

 

 

Sample Output

 

2 $1^2-3*1+2=f(1)=0$ $2^2-3*2+2=f(2)+f(1)=0->f(2)=0$ $3^2-3*3+2=f(3)+f(1)=2->f(3)=2$ $f(1)+f(2)+f(3)=2$

 

 

Source

BestCoder Round #68 (div.2)

 

 

分析:首先根据数据范围可以看出这是一道杜教筛。

同时给出了n^2-3n+2=\sum _{d|n}f(d)

此时对于g(1)S(n)=\sum_{i=1}^n\sum _{d|i}f(d)*g(\frac{i}{d})-\sum _{d=2}^ng(d)*S([\frac{n}{d}])

直接令g=I

则有S(n)=\sum_{i=1}^n i^2-3i+2-\sum _{d=2}^nS([\frac{n}{d}])

杜教筛的部分到这里就做完了,再考虑一下预处理的部分。

F(n)=n^2-3n+2=\sum _{d|n}f(d)

那么反演一下得到f(n)=\sum _{d|n}u(d)*F([\frac{n}{d}])

直接nlogn筛一下就可以了。

#include "bits/stdc++.h"

using namespace std;
const int mod = 1e9 + 7;
bool isprim[1000000];
long long mu[1000004];
long long f[1000004];
vector<long long> prim;

long long F(long long n) {
    return (n * n % mod - 3 * n % mod + 2 + mod) % mod;
}

void init() {
    memset(isprim, true, sizeof(isprim));
    memset(mu, 0, sizeof(mu));
    mu[1] = 1;
    for (int i = 2; i <= 1000000; ++i) {
        if (isprim[i]) {
            mu[i] = -1;
            prim.push_back(i);
        }
        for (int j = 0; j < prim.size() && i * prim[j] <= 1000000; ++j) {
            isprim[i * prim[j]] = 0;
            if (i % prim[j] == 0)break;
            else mu[i * prim[j]] = -mu[i];
        }
    }
    for (int i = 1; i <= 1000000; ++i) {
        for (int j = i; j <= 1000000; j += i) {
            f[j] += mu[i] * F(j / i) % mod;
            f[j] = (f[j] + mod) % mod;
        }
    }
    for (int i = 1; i <= 1000000; ++i) {
        f[i] = (f[i] + f[i - 1]) % mod;
    }
}


unordered_map<int, int> mp;

long long qk(long long a, long long n) {
    long long res = 1;
    while (n) {
        if (n & 1)res = res * a % mod;
        n >>= 1;
        a = a * a % mod;
    }
    return res;
}

long long inv(long long a) {
    return qk(a, mod - 2);
}

long long inv2 = inv(2), inv6 = inv(6);

long long getans(long long n) {
    if (mp.count(n))return mp[n];
    if (n <= 1000000)return f[n];
    long long ans = 0;
    ans = 1LL * n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod;
    ans = (ans - 3 * n % mod * (n + 1) % mod * inv2 % mod + mod) % mod;
    ans = ans + 2 * n;
    ans %= mod;
    long long l = 2, r;
    for (; l <= n; l = r + 1) {
        r = n / (n / l);
        long long temp = 1ll * (r - l + 1) * getans(n / l) % mod;
        ans = (ans - temp + mod) % mod;
    }
    return mp[n] = ans;
}

int main() {
    int n;
    init();
    int t;
    cin >> t;
    while (t--) {
        scanf("%d", &n);
        printf("%lld\n", getans(n));
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值