51nod 1594 Gcd and Phi(莫比乌斯反演)

题目链接

传送门

思路

如果这题是这样的:
\[
F(n)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\phi(gcd(i,j))
\]
那么我们可能会想到下面方法进行反演:
\[
\begin{aligned}
F(n)=&\sum\limits_{k=1}^{n}\phi(k)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[gcd(i,j)=k]&\=&\sum\limits_{k=1}^{n}\phi(k)\sum\limits_{i=1}^{\frac{n}{k}}\sum\limits_{j=1}^{\frac{n}{k}}[gcd(i,j)=1]&\\end{aligned}
\]
令\(f(n)\)为\(gcd(i,j)=n\)的有序对的对数,\(g(n)\)为\(gcd(i,j)=n\text{和}n\)的倍数的有序对的对数,则
\[
\begin{aligned}
&g(n)=\sum\limits_{n|d}f(d)&\\rightarrow&f(n)=\sum\limits_{n|d}\mu(\frac{d}{n})g(d)&
\end{aligned}
\]
然后将\(f(1)=\sum\limits_{i=1}^{n}\mu(i)g(i)\)代入\(F(n)\)得到\(F(n)=\sum\limits_{k=1}^{n}\phi(k)\sum\limits_{i=1}^{\frac{n}{k}}\mu(i)g(i)\),然后先预处理\(\sum\limits_{i=1}^{\frac{n}{k}}\mu(i)g(i)\),然后暴力枚举\(k\)或者数论分块求解答案就可以了,这里有几道类似的题目,有兴趣的可以做一下。

但是这题却不是我们所希望的那种形式,那么该怎么办呢?我们发现\(n\)小于等于\(2e6\),那么我们可以记录一下每个数的\(\phi\)是多少,然后记录一下每个\(\phi\)出现的次数后就可以转换成上述题意了(这个思想昨天的\(CCPC\)网络赛1010也用到了,不过这题由于后面不会处理就没补了23333),假设\(c_i\)表示\(\phi=i\)的个数,那么求解的式子就变成了
\[
F(n)=\sum\limits_{k=1}^{n}\phi(k)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}c_ic_j[gcd(i,j)=k]
\]
令\(f(n)\)为\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}c_ic_j[gcd(i,j)=n]\),\(g(n)\)为\(为和的倍数\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}c_ic_j[gcd(i,j)\text{为}n\text{和}n\text{的倍数}]\),则
\[
\begin{aligned}
g(n)=&\sum\limits_{n|i}\sum\limits_{n|j}c_ic_j&\=&\sum\limits_{i=1}^{n}c_i\sum\limits_{j=1}^{n}c_J&\=&(\sum\limits_{i=1}^{n}c_i)^2&\=&\sum\limits_{n|d}f(d)&
\end{aligned}
\]
那么
\[
f(n)=\sum\limits_{n|d}\mu(\frac{d}{n})g(d)
\]
最后答案为
\[
F(n)=\sum\limits_{k=1}^{n}\phi(k)f(k)
\]
然后暴力枚举\(k\)求解即可。

代码

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson (rt<<1),L,mid
#define rson (rt<<1|1),mid + 1,R
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 2000000 + 2;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

bool v[maxn];
int t, n, cnt;
int F[maxn], c[maxn], phi[maxn], p[maxn], mu[maxn];

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

int main() {
#ifndef ONLINE_JUDGE
    FIN;
    time_t s = clock();
#endif
    init();
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            ++c[phi[i]];
        }
        F[1] = c[1];
        for(int i = 2; i <= n; ++i) {
            F[1] += c[i];
            for(int j = 1; j <= n / i; ++j) {
                F[i] += c[i*j];
            }
        }
        LL sum = 1LL * F[1] * F[1], ans = 0;
        for(int i = 2; i <= n; ++i) {
            sum += 1LL* F[i] * F[i] * mu[i];
            LL tmp = 0;
            for(int j = 1; j <= n / i; ++j) {
                tmp += 1LL * F[i*j] * F[i*j] * mu[j];
            }
            ans += tmp * phi[i];
        }
        ans += sum;
        printf("%lld\n", ans);
        for(int i = 1; i <= n; ++i) F[i] = c[i] = 0;
    }
#ifndef ONLINE_JUDGE
    printf("It costs %.3fs\n", 1.0 * (clock() - s) / CLOCKS_PER_SEC);
#endif
    return 0;
}

原文地址:https://www.cnblogs.com/Dillonh/p/11406296.html

时间: 2024-07-30 14:58:29

51nod 1594 Gcd and Phi(莫比乌斯反演)的相关文章

51nod 1594 Gcd and Phi 反演

OTZ 又被吊打了...我当初学的都去哪了??? 思路:反演套路? 提交:\(1\)次 题解: 求\(\sum_{i=1}^{n}\sum_{j=1}^{n}\varphi(gcd(\varphi(i),\varphi(j)))\) 设\(c[i]=\sum_{j=1}^n[\varphi(j)==i]\) 有: \(\sum_{i=1}^{n}\sum_{j=1}^{n}\varphi(gcd(i,j))*c[i]*c[j]\) 欧拉反演一下,把\(gcd\)扔出来 \(\sum_{i=1}^

【Project Euler】530 GCD of Divisors 莫比乌斯反演

[题目]GCD of Divisors [题意]给定f(n)=Σd|n gcd(d,n/d)的前缀和F(n),n=10^15. [算法]莫比乌斯反演 [题解]参考:任之洲数论函数.pdf 这个范围显然杜教筛也是做不了的,而且考虑直接化简f(n)也遇到了困难,所以考虑将前缀和的Σ一起化简. $$F(n)=\sum_{i=1}^{n}\sum_{d|i}(d,\frac{i}{d})$$ 这一步很常见的是第一重改为枚举倍数,但这样化简后面就推不下去了. 这道题必须最后转成$\sigma_0(n)$才

bnu——GCD SUM (莫比乌斯反演)

题目:GCD SUM 题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=39872 算法:莫比乌斯反演.优化 1 #include<stdio.h> 2 #define N 100001 3 typedef long long LL; 4 bool pri[N]={0}; 5 int prim[N],po=0; 6 int mu[N]; 7 LL f[N],ff[N]; //缩短时间 8 /* 9 莫比乌斯函数mu[i]的定义: 10 1. 如

【51nod】1222 最小公倍数计数 莫比乌斯反演+组合计数

[题意]给定a和b,求满足a<=lcm(x,y)<=b && x<y的数对(x,y)个数.a,b<=10^11. [算法]莫比乌斯反演+组合计数 [题解]★具体推导过程参考:51nod1222 最小公倍数计数 过程运用到的技巧: 1.将所有i和j的已知因子提取出来压缩上届. 2.将带有μ(k)的k提到最前面,从而后面变成单纯的三元组形式. 最终形式: $$ans=\sum_{k=1}^{\sqrt n} \mu(k)  \sum_{d}    \sum_{i} \s

51nod 1222 最小公倍数计数【莫比乌斯反演】

参考:https://www.cnblogs.com/SilverNebula/p/7045199.html 所是反演其实反演作用不大,又是一道做起来感觉诡异的题 转成前缀和相减的形式 \[ \sum_{i=1}^{n}\sum_{j=1}^{n}[\frac{i*j}{gcd(i,j)}\leq n] \] \[ \sum_{d=1}^{n}\sum_{i=1}^{\left \lfloor \frac{n}{d}\right \rfloor}\sum_{j=1}^{\left \lfloor

SPOJ - PGCD Primes in GCD Table(莫比乌斯反演)

http://www.spoj.com/problems/PGCD/en/ 题意: 给出a,b区间,求该区间内满足gcd(x,y)=质数的个数. 思路: 设f(n)为 gcd(x,y)=p的个数,那么F(n)为 p | gcd(x,y)的个数,显然可得F(n)=(x/p)*(y/p). 这道题目因为可以是不同的质数,所以需要枚举质数, 但是这样枚举太耗时,所以在这里令t=pk, 这样一来的话,我们只需要预处理u(t/p)的前缀和,之后像之前的题一样分块处理就可以了. 1 #include<ios

BZOJ 2818 Gcd (莫比乌斯反演 或 欧拉函数)

2818: Gcd Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2534  Solved: 1129 [Submit][Status][Discuss] Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的 数对(x,y)有多少对. Input 一个整数N Output 如题 Sample Input 4 Sample Output 4 HINT hint 对于样例(2,2),(2,4),(3,3),(4,2)

【51Nod 1237】最大公约数之和 V3 莫比乌斯反演+杜教筛

题意 求$\sum_{i=1}^{n}\sum_{j=1}^{n}(i,j)$ 枚举约数 $$ \begin{align} ans &=\sum_{d=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{n}[(i,j)=d] \ &=\sum_{d=1}^{n}\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor \frac{n}{d} \rfloor}[(i,j)=1] \ \end{align} $$ 利用

hdu_1695: GCD 【莫比乌斯反演】

题目链接 这题求[1,n],[1,m]gcd为k的对数.而且没有顺序. 设F(n)为公约数为n的组数个数 f(n)为最大公约数为n的组数个数 然后在纸上手动验一下F(n)和f(n)的关系,直接套公式就好了.注意要删去重复的. 关于 莫比乌斯反演 的结论 #include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1e6; int prime[maxn+5]; bool check[maxn+