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
分析:首先根据数据范围可以看出这是一道杜教筛。
同时给出了
此时对于
直接令
则有
杜教筛的部分到这里就做完了,再考虑一下预处理的部分。
那么反演一下得到
直接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));
}
}