吉首大学 问题 L: 小李子的老年生活

时间限制: 1 Sec  内存限制: 128 MB
提交: 719  解决: 27
题目描述

小李子有n-1个朋友,分别编号为1..n-1,小李子的编号是n ,小李子的表面朋友的编号会与小李子编号互质

我们定义小李子老年生活的悲惨度是表面朋友的编号的平方和

输入

多组输入(小于等于10000组)

每组输入一个n( <= 1e6 )

输出

输出小李子的悲惨度

样例输入
2
3
样例输出
1
5
【分析】:http://cubercsl.cn/solve/contest/%E5%B0%8F%E6%9D%8E%E5%AD%90%E7%9A%84%E8%80%81%E5%B9%B4%E7%94%9F%E6%B4%BB/#more
  • 容易想到用莫比乌斯反演:
s(n)=j=1,(n,j)=1nj2=j=1n(j2d|(n,j)μ(d))=d|n(μ(d)1jn,d|jj2)=∑d|n(μ(d)∑j=1ndj2d2)=∑d|nμ(d)(n33d+n22+nd6)=16(2n2φ(n)+∑d|nμ(d)d
用筛法预处理求一下和就好了。
【代码】:
#include <bits/stdc++.h>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define X first
#define Y second
#define fastin                    
    ios_base::sync_with_stdio(0); 
    cin.tie(0);
typedef long long ll;
typedef long double ld;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;

const int maxn = 1e6 + 5;
int prime[maxn], tot, mu[maxn];
ll diri[maxn];
bool check[maxn];
void calmu()
{
    mu[1] = 1;
    for (int i = 2; i < maxn; i++)
    {
        if (!check[i]) prime[tot++] = i, mu[i] = -1;
        for (int j = 0; j < tot; j++)
        {
            if (i * prime[j] >= maxn) break;
            check[i * prime[j]] = true;
            if (i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            else
                mu[i * prime[j]] = -mu[i];
        }
    }
}

int phi[maxn] = {0, 1};
void CalEuler()
{
    for (int i = 2; i < maxn; i++)
        if (!phi[i])
            for (int j = i; j < maxn; j += i)
            {
                if (!phi[j]) phi[j] = j;
                phi[j] = phi[j] / i * (i - 1);
            }
}

void init()
{
    for (int i = 1; i < maxn; i++) diri[i] = 1;
    for (int i = 2; i < maxn; i++)
    {
        for (int j = i; j < maxn; j += i)
            diri[j] += i * mu[i];
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    calmu();
    CalEuler();
    init();
    ll n;
    while (cin >> n)
    {
        ll ans = (n * n * phi[n] * 2 + n * diri[n]) / 6;
        cout << ans << endl;
    }
    return 0;
}
数论

原文地址:https://www.cnblogs.com/Roni-i/p/8252403.html