转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题意 :求满足gcd(i , j)是素数(1 <= i <= n && 1 <= j <= m)二元组(i , j)个数。

很值得总结的题。。。

首先得会一点前提东西 。。。先简单说下Mobius反演,就是偏序集上的容斥原理。

定义

F(n) = sigma (G(d))   d | n

那么G(n) = sigma (F(d) * miu (n / d))  d | n

还有另外一个表达形式

F(n) = sigma (G(d))  n | d

G(n) = sigma (F(d) * miu (d / n))  n | d

miu(i)是莫比乌斯函数

1                (i = 1)

miu(i) =    (-1) ^ k       (i是square free number,k是i的素因子个数)

0                (其它情况)

然后 就是要会求一个东西 GCD (i , j) = k 的数量。 (可以拿SPOJ   VLATTICE  先练练)

令F(k)表示GCD(i , j) >= k的数量。    这个东西 比较好求 就是(n / k) * (m / k)

然后令G(k)表示GCD(i , j) = k的数量。这个东西不 好求,就可以反演出来了

显然F(k) = sigma (G[d])  k | d

则G(k) = sigma (G[d] * miu (d / k))  k | d

这样就可以枚举d做出来了。。。。

对于这题,分成三个阶段。。。

stage 1 :打个素数表,然后预处理出miu函数。那么直接枚举素数p,求gcd(i , j) = p的数量,然后累加就行了。

预处理可以用线性筛选搞到O(n),每次查询是O(prime_count(n) * n)。显然会TLE。。。。

stage 2 :整理1中的式子,求的是sigma(F(d) * miu(d / p))  p为素数。

那么其中的F(d)只和d有关。。。可以枚举d,那么就要求出P[d] = sigma(miu(d / p))了p是d的某一个素因子。。。

如果d = p1 ^ k1 * p2 ^ k2 * …… pm ^ km

1、如果ki全为1,那么d / pi是square free number,而且素因子个数为m - 1。答案就是((m - 1) & 1 ? -1 : 1) * m

2、如果ki中只有1个为2,那么如果pi的指数为1,那么d / pi肯定不是square free number,那么miu值为0,不用管。如果pi的指数为2的话,那么d / pi肯定是square free number,素因子数个还为m,答案就是(m & 1 ? -1 : 1)

3、其余情况d / pi肯定不是square free number,miu值全为0,答案就是0.

处理完之后,对于查询只需要枚举d,然后 sigma(F(d) * P(d))

预处理同样可以用线性筛选完成O(n),每次查询O(n)。但是还是TLE。。。好SXBK。

PS:线性筛选太强大了。。。记录了每一个合数的最小素因子,保证每个合数最多被筛一次,保证了线性复杂度。

而且有了最小素因子minumfac[],就可以记录素因子个数totnum[]以及不同的素因子个数diffnum[]。就可以处理出P[]。

stage 3:又是经典的分块,考虑F(d) = (n / d) * (m / d),这个东西只有log()级别种,相邻的部分值是一样的。

对于这种分块不熟的可以做CQOI2007 余数之和sum

这样的话预处理O(n),查询O(sqrt(n))。。。终于过了

PS:SPOJ把MLE判成RE,然后 我就RE了10多次。。。。。线性筛选的时候少了一句话,又TLE好多次。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define pii pair<int,LL>
using namespace std;
typedef long long LL;
const int N = 10000005;
int cnt = 0 , prime[N] , minumfac[N];
int totnum[N] , diffnum[N] , p[N];
bool isnotprime[N];
// int miu[N];
void init () {isnotprime[0] = isnotprime[1] = true;cnt = 0 ; // miu[1] = 1;for (int i = 2 ; i < N ; i ++) {if (!isnotprime[i]) {prime[cnt ++] = i;// miu[i] = -1;}for (int j = 0 ; j < cnt && i * prime[j] < N ; j ++) {isnotprime[i * prime[j]] = true;minumfac[i * prime[j]] = prime[j];// if (i % prime[j] == 0) miu[i * prime[j]] = 0;// else miu[i * prime[j]] = - miu[i];if (i % prime[j] == 0) break;}}p[1] = 0;for (int i = 2 ; i < N ; i ++) {if (!isnotprime[i]) totnum[i] = diffnum[i] = 1;else {totnum[i] = totnum[i / minumfac[i]] + 1;diffnum[i] = diffnum[i / minumfac[i]] + ((i / minumfac[i]) % minumfac[i] != 0);}if (totnum[i] == diffnum[i]) p[i] = (((totnum[i] - 1) & 1) ? -1 : 1) * totnum[i];else if (totnum[i] - diffnum[i] == 1) p[i] = (diffnum[i] & 1) ? -1 : 1;else p[i] = 0;p[i] += p[i - 1];}
}int main () {#ifndef ONLINE_JUDGEfreopen ("input.txt" , "r" , stdin);// freopen ("output.txt" , "w" , stdout);#endifint t;scanf ("%d" , &t);init ();while (t --) {int n , m ;LL ans = 0;scanf ("%d %d" , &n , &m);if (n > m) swap (n , m);/* // stage 1:// make talbe : O(n)// for every query : O(n * prime_count(n))for (int i = 0 ; i < cnt ; i ++) {int p = prime[i];for (int j = p ; j <= n ; j += p) {#define f(a , b , p) ((a / p) * (b / p))ans += miu[j / p] * f(n , m , j);}}*//*// stage 2:// make table : O(n)// for every query : O(n)for (int i = 1 ; i <= n ; i ++) {#define f(d) ((n / d) * (m / d))ans += p[i] * f(i);}*/// stage 3:// make table : O(n)// for every query : O(sqrt (n))for (int i = 2 , next; i <= n ; i = next) {int d1 = n / i , d2 = m / i;int next_n = n / d1 + 1 , next_m = m / d2 + 1;next = min (next_m , next_n);ans += 1LL * (p[next - 1] - p[i - 1]) * d1 * d2;}printf ("%lld\n" , ans);}return 0;
}       

SPOJ PGCD (mobius反演 + 分块)相关推荐

  1. Bzoj-2820 YY的GCD Mobius反演,分块

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2820 题意:多次询问,求1<=x<=N, 1<=y<=M且gcd( ...

  2. Mobius反演总结

    刷了一些浅显的反演题目, 做一个总结 知识点1 给定n个数(可以是1-n), 求有多少数与x互质 f(x)=∑d|xu[d]∗cnt[d] f(x) = \sum_{d|x}u[d]*cnt[d] 其 ...

  3. Mobius反演学习

    这篇文章参考了许多资料和自己的理解. 先放理论基础. 最大公约数:小学学过,这里只提一些重要的公式: $·$若$a=b$,则$\gcd(a,b)=a=b$: $·$若$\gcd(a,b)=d$,则$\ ...

  4. 关于Mobius反演

    欧拉函数 \(\varphi\) \(\varphi(n)=\)表示不超过 \(n\) 且与 \(n\) 互质的正整数的个数 \[\varphi(n)=n\cdot \prod_{i=1}^{s}(1 ...

  5. Mobius反演和筛法

    Mobius反演和筛法 前置知识:积性函数.Dirichlet卷积.莫比乌斯函数.数论分块 积性函数 定义: 1.若f(n)的定义域为正整数域,值域为复数,即f: Z^+ →C,则f(n)为数论函数: ...

  6. Mobius反演方法

    <更新提示> 前置知识:建议有一点DirichletDirichletDirichlet卷积的基础,会线性筛求积性函数.本文可能会持续更新. 可以看我以前在博客园的博客. <正文&g ...

  7. BZOJ 1101 Luogu P3455 POI 2007 Zap (莫比乌斯反演+分块)

    URL: (Luogu)https://www.luogu.org/problem/show?pid=3455 (BZOJ)http://www.lydsy.com/JudgeOnline/probl ...

  8. P1829 [国家集训队]Crash的数字表格(推了好久的mobius反演)

    P1829 [国家集训队]Crash的数字表格 / JZPTAB 推导过程 ∑i=1n∑j=1mlcm(i,j)\sum_{i = 1} ^{n} \sum_{j = 1} ^{m} lcm(i, j ...

  9. P3327 [SDOI2015]约数个数和 (mobius反演)

    P3327 [SDOI2015]约数个数和 推导过程 求∑i=1n∑j=1md(ij)\sum_{i = 1} ^{n} \sum_{j = 1} ^{m} d(ij)∑i=1n​∑j=1m​d(ij ...

最新文章

  1. 古代荀子也懂AI?达芬奇的手术机器人有多神奇? 听浙大吴飞扒一扒人工智能的“古今中外”!
  2. 访中科曙光智能计算技术总监许涛:重新认识面向未来的AI服务器和云计算中心...
  3. python3入门到精通pdf-总算知道python3入门到精通
  4. [C#]泛型与非泛型集合类的区别及使用例程,包括ArrayList,Hashtable,ListT,DictionaryTkey,Tvalue,SortedListTkey,Tvalue,...
  5. Docker Compose编排(写法格式及实验)
  6. oracle数据库延迟执行,如何诊断oracle数据库运行缓慢或hang住的问题
  7. python-发送短信验证码-功能的实现
  8. ShardingSphere(四) 垂直分库配置搭建,实现写入读取
  9. 随想录(ccpp之间的相互调用)
  10. initBinder转换日期格式
  11. 【Oracle】查询当前SCN
  12. ssl介绍以及双向认证和单向认证原理
  13. [转载] python3 闭包
  14. 在C / C ++中使用INT_MAX和INT_MIN
  15. Android Studio开发
  16. Keil5安装教程(包含C51与MDK共存)WIN10 亲测可用
  17. #foxpro(VFP) 入门(一) 常用命令
  18. JavaScript中的call(),apply(),伪数组转化为数组
  19. android 文本倒影,Android 生成倒影图片
  20. python数据分析案例简单实战项目(一)--供应链销售数据分析

热门文章

  1. 谷歌医疗AI又有新进展:转移性乳腺癌检测准确率达99%
  2. DeepMind去年亏损27亿元,同比扩大221%,谷歌说:继续烧
  3. 无人车创业正驶入分水岭
  4. 不再需要词典了,现在,AI通过无监督学习学会了双语翻译
  5. 谷歌推出理解神经网络的新方法SVCCA | NIPS论文+代码
  6. [20180503]珅与分隔符.txt
  7. 动画 - 收藏集 - 掘金
  8. YUV格式文件转RGB格式
  9. Flex 布局实例教程
  10. 使用auditctl追踪文件变化