hdu5608 function

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$

Solution

两种方法:杜教筛,杜教筛+莫比乌斯反演

1.杜教筛+莫比乌斯反演

这貌似是我第一次真正意义上用莫比乌斯反演公式。。。
(F(n)=sum_{d|n}f(d)=n^2-3n+2)
则有(f(n)=sum_{d|n}mu(d)F(frac{n}{d}))

[egin{aligned} &sum_{i=1}^{n}f(i)\ &=sum_{i=1}^{n}sum_{d|i}mu(d)F(frac{n}{d})\ &=sum_{d=1}^nmu(d)sum_{i=1}^{lfloorfrac{n}{d} floor}F(i) end{aligned} ]

前面那个(mu(d))杜教筛,后面那个推一下可以(O(1))
(sum_{i=1}^n{i^2-3i+2}=frac{n(n-1)(n-2)}{3})

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <deque>
#include <map>
#include <set>

#define ll long long
#define inf 0x3f3f3f3f
#define il inline

namespace io {

#define in(a) a = read()
#define out(a) write(a)
#define outn(a) out(a), putchar('
')

#define I_int ll
inline I_int read() {
    I_int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}
char F[200];
inline void write(I_int x) {
    if (x == 0) return (void) (putchar('0'));
    I_int tmp = x > 0 ? x : -x;
    if (x < 0) putchar('-');
    int cnt = 0;
    while (tmp > 0) {
        F[cnt++] = tmp % 10 + '0';
        tmp /= 10;
    }
    while (cnt > 0) putchar(F[--cnt]);
}
#undef I_int

}
using namespace io;

using namespace std;

const int N = 5e6;
const ll mod = 1e9 + 7;

ll n, m;
bool vis[N+10];
int p[N/10], cnt;
int mu[N], s[30000];

void init(int n) {
	mu[1] = 1;
	for(int i = 2; i <= n; ++i) {
		if(!vis[i]) p[++cnt] = i, mu[i] = -1;
		for(int j = 1; j <= cnt && i * p[j] <= n; ++j) {
			vis[i * p[j]] = 1;
			if(i % p[j] == 0) break;
			mu[i * p[j]] = -mu[i];
		}
	}
	for(int i = 1; i <= n; ++i) mu[i] += mu[i - 1];
}

int S(ll n) {
	if(n <= N) return mu[n];
	if(vis[m / n]) return s[m / n];
	vis[m / n] = 1;
	int ans = 1;
	for(ll l = 2, r; l <= n; l = r + 1) {
		r = n / (n / l);
		ans -= (r - l + 1) * S(n / l);
		ans %= mod; ans += mod; ans %= mod;
	}
	return s[m / n] = ans;
}

ll power(ll a, ll b) { ll ans = 1;
	while(b) {
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod; b >>= 1;
	} 
	return ans;
}

ll inv3 = power(3, mod - 2);
ll calc(ll n) {
	return n * (n - 1) % mod * (n - 2) % mod * inv3 % mod;
}

int main() {
	init(N);
	int T = read();
	while(T--) {
		n = read();
		memset(vis, 0, sizeof(vis));
		m = n;
		ll ans = 0;
		for(ll l = 1, r; l <= n; l = r + 1) {
			r = n / (n / l);
			ans += 1ll * (S(r) - S(l - 1) + mod) % mod * calc(n / l) % mod ;
			ans %= mod;
		}
		printf("%lld
", ans);
	}
}

2.杜教筛

现在才知道杜教筛可以筛普通数论函数,不一定要积性函数。
那么就很简单了,套路的给(f)卷上(1),则有(f*1=g=n^2-3n+2)
至于预处理g的前缀和,这玩意不是积性函数不能线性筛。但是可以(nlogn)暴力筛出来。方法很多,因为我是写了方法1再来写方法2的所以我直接又反演了一下来筛。。。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <deque>
#include <map>
#include <set>

#define ll long long
#define inf 0x3f3f3f3f
#define il inline

namespace io {

#define in(a) a = read()
#define out(a) write(a)
#define outn(a) out(a), putchar('
')

#define I_int ll
inline I_int read() {
    I_int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}
char FF[200];
inline void write(I_int x) {
    if (x == 0) return (void) (putchar('0'));
    I_int tmp = x > 0 ? x : -x;
    if (x < 0) putchar('-');
    int cnt = 0;
    while (tmp > 0) {
        FF[cnt++] = tmp % 10 + '0';
        tmp /= 10;
    }
    while (cnt > 0) putchar(FF[--cnt]);
}
#undef I_int

}
using namespace io;

using namespace std;

const int N = 1e6;
const ll mod = 1e9 + 7;

ll n, m;
bool vis[N+10];
int p[N/10], cnt;
ll s[N], F[N];

ll power(ll a, ll b) { ll ans = 1;
	while(b) {
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod; b >>= 1;
	} 
	return ans;
}

ll inv3 = power(3, mod - 2);
ll calc(ll n) {
	n %= mod;
	return n * (n - 1) % mod * (n - 2) % mod * inv3 % mod;
}

int mu[N];
void init(int n) {
	mu[1] = 1;
	for(int i = 2; i <= n; ++i) {
		if(!vis[i]) p[++cnt] = i, mu[i] = -1;
		for(int j = 1; j <= cnt && i * p[j] <= n; ++j) {
			vis[i * p[j]] = 1;
			if(i % p[j] == 0) break;
			mu[i * p[j]] = -mu[i];
		}
	}
	for(int i = 1; i <= n; ++i) {
		ll g = (ll)(((ll)i * i % mod - 3ll * i % mod + 2ll) % mod + mod) % mod;
		for(int j = i; j <= n; j += i) {
			F[j] += 1ll * mu[j / i] * g % mod;
			F[j] %= mod;
		}
	}
	for(int i = 1; i <= n; ++i) F[i] += F[i - 1], F[i] %= mod;
}

ll S(ll n) {
	if(n <= N) return F[n];
	if(vis[m / n]) return s[m / n];
	vis[m / n] = 1;
	ll ans = calc(n);
	for(ll l = 2, r; l <= n; l = r + 1) {
		r = n / (n / l);
		ans -= (r - l + 1) * S(n / l) % mod;
		ans %= mod; ans += mod; ans %= mod;
	}
	return s[m / n] = (ans % mod + mod) % mod;
}

int main() {
	init(N);
	int T = read();
	while(T--) {
		n = read();
		memset(vis, 0, sizeof(vis));
		m = n;
		printf("%lld
", (S(n) + mod) % mod);
	}
}
原文地址:https://www.cnblogs.com/henry-1202/p/10363375.html