51nod 1594 Gcd and Phi(莫比乌斯反演)
Posted dillonh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1594 Gcd and Phi(莫比乌斯反演)相关的知识,希望对你有一定的参考价值。
题目链接
思路
如果这题是这样的:
\\[
F(n)=\\sum\\limits_i=1^n\\sum\\limits_j=1^n\\phi(gcd(i,j))
\\]
那么我们可能会想到下面方法进行反演:
\\[
\\beginaligned
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^\\fracnk\\sum\\limits_j=1^\\fracnk[gcd(i,j)=1]&\\\\endaligned
\\]
令\\(f(n)\\)为\\(gcd(i,j)=n\\)的有序对的对数,\\(g(n)\\)为\\(gcd(i,j)=n\\text和n\\)的倍数的有序对的对数,则
\\[
\\beginaligned
&g(n)=\\sum\\limits_n|df(d)&\\\\rightarrow&f(n)=\\sum\\limits_n|d\\mu(\\fracdn)g(d)&
\\endaligned
\\]
然后将\\(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^\\fracnk\\mu(i)g(i)\\),然后先预处理\\(\\sum\\limits_i=1^\\fracnk\\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^nc_ic_j[gcd(i,j)=k]
\\]
令\\(f(n)\\)为\\(\\sum\\limits_i=1^n\\sum\\limits_j=1^nc_ic_j[gcd(i,j)=n]\\),\\(g(n)\\)为\\(为和的倍数\\sum\\limits_i=1^n\\sum\\limits_j=1^nc_ic_j[gcd(i,j)\\text为n\\text和n\\text的倍数]\\),则
\\[
\\beginaligned
g(n)=&\\sum\\limits_n|i\\sum\\limits_n|jc_ic_j&\\=&\\sum\\limits_i=1^nc_i\\sum\\limits_j=1^nc_J&\\=&(\\sum\\limits_i=1^nc_i)^2&\\=&\\sum\\limits_n|df(d)&
\\endaligned
\\]
那么
\\[
f(n)=\\sum\\limits_n|d\\mu(\\fracdn)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;
以上是关于51nod 1594 Gcd and Phi(莫比乌斯反演)的主要内容,如果未能解决你的问题,请参考以下文章