题目大意

给出一段序列,求其中最大公约数为1的四元组的个数。

思路

我们要用到反演、正难则反的思想。对于每一个大于1的数字\(x\),求出最大公约数为\(x\)的四元组的个数\(g(x)\),然后用排列中所有四元组的组合个数减去\(\sum g(x)\)即可。

直接求\(g(x)\)没有什么思路,但是求公约数中存在\(x\)的四元组的个数\(f(x)\)会比较容易。枚举约数中存在x的数列元素的个数\(n\),则有

\[f(x)=C_n^4
\]

那么怎么把\(f(x)\)变为\(g(x)\)呢?这要用到莫比乌斯反演。

莫比乌斯反演

莫比乌斯函数

\[\mu(x)=
\begin{cases}
1 &\text{若$x$=1}\\
0 &\text{若对$x$质因数分解得到的每个质数的次数中存在大于1的}\\
(-1)^k &\text{$k$为$x$的质因数个数}
\end{cases}
\]

莫比乌斯反演公式

\[f(x)=\sum_{k=1}^{\lfloor \frac{N}{x}\rfloor}g(kx)\tag{1}
\]

\[g(x)=\sum_{k=1}^{\lfloor \frac{N}{x}\rfloor}f(kx)\mu(k)
\]

我们发现这道题若把序列中的数字最大值作为\(N\),\(f(x),g(x)\)恰好满足该关系(1)。于是我们跟着公式求\(g(x)\)即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define ll long long const int MAX_N = 10010, MAX_R = 5, MAX_PRIME_CNT = MAX_N;
ll C[MAX_N][MAX_R];
int Num[MAX_N], Mu[MAX_N];
ll F[MAX_N]; void GetMu(int *mu, int n)
{
static bool NotPrime[MAX_N];
static int prime[MAX_PRIME_CNT];
memset(NotPrime, false, sizeof(NotPrime));
int primeCnt = 0;
mu[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!NotPrime[i])
{
prime[primeCnt++] = i;
mu[i] = -1;
}
for (int j = 0; j < primeCnt; j++)
{
if (i*prime[j] > n)
break;
NotPrime[i*prime[j]] = true;
if (i%prime[j] == 0)
{
mu[i*prime[j]] = 0;
break;
}
else
mu[i*prime[j]] = -mu[i];
}
}
} void GetC(int r, int n)
{
memset(C, 0, sizeof(C));
for (int i = 1; i <= n; i++)
{
C[i][0] = 1;
for (int j = 1; j <= min(i, r); j++)
{
if (i == j)
C[i][j] = 1;
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
} ll Proceed(int maxN, int n)
{
memset(F, 0, sizeof(F));
for (int i = 2; i <= maxN; i++)
{
int cnt = 0;
for (int j = 1; j <= maxN / i; j++)
cnt += Num[i * j];
F[i] = C[cnt][4];
}
ll ans = 0;
for (int i = 2; i <= maxN; i++)
for (int j = 1; j <= maxN / i; j++)
ans += F[i * j] * Mu[j];
return C[n][4] - ans;
} int main()
{
GetMu(Mu, 10000);
GetC(4, 10000);
int n, maxN = 0, x;
while (~scanf("%d", &n))
{
memset(Num, 0, sizeof(Num));
for (int i = 1; i <= n; i++)
{
scanf("%d", &x);
Num[x]++;
maxN = max(maxN, x);
}
printf("%lld\n", Proceed(maxN, n));
}
return 0;
}

最新文章

  1. WinForm 中TreeView 控件的使用实例
  2. sql基础语句
  3. Puppet权威指南
  4. Delphi项目构成之单元文件PAS
  5. threadid=1: thread exiting with uncaught.exception ......解决方法
  6. diff和patch配合使用(转载备用)
  7. cocos2d-x 中 TTF 字体文件的位置
  8. 在阿里云 CentOS 服务器(ECS)上搭建 nginx + mysql + php-fpm 环境
  9. 首发Zend Studio 10.6正式版注册破解(2014-02-06更新)
  10. Java split用法
  11. Java事务处理总结
  12. 高性能动画!HTML5 Canvas JavaScript框架KineticJS
  13. solaris 操作系统配置联网
  14. hadoop重新启动之后Datanode无法启动的问题
  15. 关于DCL的使用
  16. 安装oh-my-zsh
  17. SSM框架中的注解,配置和控制器相关笔记
  18. ACM-自学之旅
  19. react中如何使用动画效果
  20. hermes kafka 转http rest api 的broker 工具

热门文章

  1. DOM 介绍
  2. C#Cookie操作类,删除Cookie,给Cookie赋值
  3. C# 对象克隆,DataTable转LIST
  4. Go中的main函数和init函数
  5. IVVI SK3-02小骨酷派SK3-02 进入第三方 recovery 刷机 ROOT
  6. hibernate_05_单表操作_对象类型
  7. VHDL之concurrent之block
  8. dubbo之直连提供者
  9. Morse理论:拓扑不变性特征匹配原理
  10. 【sicily】 1934. 移动小球