1.题目链接。应该说有一段时间莫得写数论了。今天写了模板题。
2.分析:直接推导,可以有两种方式。比较暴力的方式:
(1)
对于后边那个式子,我们知道他就是欧拉函数的前缀和,然后可以继续:
求欧拉函数前缀和之后分块即可。
/**************************************************************
Problem: 4804
User: wsyingang
Language: C++
Result: Accepted
Time:3700 ms
Memory:167304 kb
****************************************************************/
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
const int m = 1e7;
int prime[N], tot, phi[N];
#define ll long long
#pragma warning(disable:4996)
ll sum[N];
bool vis[N];
void init()
{
sum[1] = phi[1] = 1;
for(int i=2;i<=m;i++)
{
if (!vis[i])phi[i] = i - 1, prime[++tot] = i;
for (int j = 1; j <= tot && i*prime[j] <= m; j++)
{
vis[i*prime[j]] = 1;
if (i%prime[j] == 0)
{
phi[i*prime[j]] = phi[i] * prime[j];
break;
}
else
{
phi[i*prime[j]] = phi[i] * (prime[j] - 1);
}
}
sum[i] =sum[i - 1] + phi[i];
}
}
int main()
{
init();
int t;
scanf("%d", &t);
ll ans = 0;
while (t--)
{
int n;
scanf("%d", &n);
int last;
ans = 0;
for (int i = 1; i <= n; i=last + 1)
{
last = n / (n/i);
ans += (sum[last] - sum[i - 1])*sum[n / i];
}
printf("%lld\n", 2 * ans - sum[n]);
}
}
(2)采用积性函数线性筛:
然后就是筛f函数了,积性函数的思想。
/**************************************************************
Problem: 4804
User: wsyingang
Language: C++
Result: Accepted
Time:4244 ms
Memory:167304 kb
****************************************************************/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M = 1e7 + 5;
int n, h[M], prime[M], cnt;
bool not_prime[M];
ll ans, sum[M];
void solve() {
ans = 0;
scanf("%d", &n);
for (int i = 1, r; i <= n; i = r + 1) {
r = n / (n / i);
ans += (ll)(n / i)*(n / i)*(sum[r] - sum[i - 1]);
}
printf("%lld\n", ans);
}
int main() {
h[1] = 1;
for (int i = 2; i <= 1e7; i++) {
if (!not_prime[i]) {
prime[++cnt] = i;
h[i] = i - 2;
}
for (int j = 1; j <= cnt && i*prime[j] <= 1e7; j++)
{
not_prime[i*prime[j]] = 1;
if (i%prime[j] == 0) {
if (i / prime[j] % prime[j] == 0)
h[i*prime[j]] = h[i] * prime[j];
else h[i*prime[j]] = h[i / prime[j]] * (prime[j] - 1)*(prime[j] - 1);
break;
}
h[i*prime[j]] = h[i] * h[prime[j]];
}
}
for (int i = 1; i <= 1e7; i++) sum[i] = sum[i - 1] + h[i];
int t;
scanf("%d", &t);
while (t--) solve();
return 0;
}