SPOJ PGCD (mobius反演 + 分块)
转载请注明出处,谢谢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_JUDGE
freopen ("input.txt" , "r" , stdin);
// freopen ("output.txt" , "w" , stdout);
#endif
int 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反演 + 分块)的更多相关文章
- Bzoj-2820 YY的GCD Mobius反演,分块
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2820 题意:多次询问,求1<=x<=N, 1<=y<=M且gcd( ...
- SPOJ PGCD(莫比乌斯反演)
传送门:Primes in GCD Table 题意:给定两个数和,其中,,求为质数的有多少对?其中和的范围是. 分析:这题不能枚举质数来进行莫比乌斯反演,得预处理出∑υ(n/p)(n%p==0). ...
- bzoj 2820 / SPOJ PGCD 莫比乌斯反演
那啥bzoj2818也是一样的,突然想起来好像拿来当周赛的练习题过,用欧拉函数写掉的. 求$(i,j)=prime$对数 \begin{eqnarray*}\sum_{i=1}^{n}\sum_{j= ...
- Bzoj-2301 [HAOI2011]Problem b 容斥原理,Mobius反演,分块
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 题意:多次询问,求有多少对数满足 gcd(x,y)=k, a<=x<=b ...
- 关于Mobius反演
欧拉函数 \(\varphi\) \(\varphi(n)=\)表示不超过 \(n\) 且与 \(n\) 互质的正整数的个数 \[\varphi(n)=n\cdot \prod_{i=1}^{s}(1 ...
- mobius反演讲解
mobius反演的基本形式为,假设知道函数F(x)=Σf(d) d|x,那么我们可以推出f(x)=Σmiu(d)*F(x/d) d|x,另一基本形式为假设知道函数F(x)=Σf(d) x|d,那么我们 ...
- [基本操作] Mobius 反演, Dirichlet 卷积和杜教筛
Dirichlet 卷积是两个定义域在正整数上的函数的如下运算,符号为 $*$ $(f * g)(n) = \sum_{d|n}f(d)g(\frac{n}{d})$ 如果不强调 $n$ 可简写为 $ ...
- Mobius反演与积性函数前缀和演学习笔记 BZOJ 4176 Lucas的数论 SDOI 2015 约数个数和
下文中所有讨论都在数论函数范围内开展. 数论函数指的是定义域为正整数域, 且值域为复数域的函数. 数论意义下的和式处理技巧 因子 \[ \sum_{d | n} a_d = \sum_{d | n} ...
- Mobius反演学习
这篇文章参考了许多资料和自己的理解. 先放理论基础. 最大公约数:小学学过,这里只提一些重要的公式: $·$若$a=b$,则$\gcd(a,b)=a=b$: $·$若$\gcd(a,b)=d$,则$\ ...
随机推荐
- Linux下解决高并发socket最大连接数所受的各种限制(解除IO限制)
linux作为服务器系统,当运行高并发TCP程序时,通常会出现连接建立到一定个数后不能再建立连接的情况 本人在工作时,测试高并发tcp程序(GPS服务器端程序),多次测试,发现每次连接建立到3800左 ...
- js 函数参数形式
1. var a = function(b,c){ console.log(arguments);}a("1","cc"); -> ["1&q ...
- thinkphp中ajax用户名校验
ajax实在是太神奇了,刚刚接触,不足之处,请大家指正. 采用Ajax方式进行页面无刷新提示,来检测用户名是否存在. 搭建一个thinkphp的环境,在index.html中,ajax代码如下: &l ...
- 加入BOINC(伯克利开放式网络计算平台)
转载:BOINC:为科学而计算 通过 BOINC 你可以将闲置的计算机时间贡献给 SETI@home, Climateprediction.net, Rosetta@home, World Commu ...
- 你好,C++(37)上车的人请买票!6.3.3 用虚函数实现多态
6.3.3 用虚函数实现多态 在理解了面向对象的继承机制之后,我们知道了在大多数情况下派生类是基类的“一种”,就像“学生”是“人”类中的一种一样.既然“学生”是“人”的一种,那么在使用“人”这个概念 ...
- CRM窗体中只读的控件不会引发Update事件
在CRM的窗体设计时,如果把某一个控件设为只读了,仅管你在后台用代码修改了值,这个值也不会起任何作用,更不会提交到后台,触发Update事件!
- powerpoint2015如何调整PPT立体图形
在powerpoint2016中,可以添加图片来丰富演说,但通常人们只会懂得插入平面图片.动态图片,立体图片就无法插入了吗?不是的,在powerpoint2016为我们准备了大量的预设,可以调整图片, ...
- sql char类型的空处理
对是varchar类型的数据进行不是空的判断时,可以采用 --<>''或者!='' int类型的数据可以采用 is not null,但是它对char类型的数据没用 distinct 用于 ...
- Jedis 一
//连接Jedis public Jedis getJedis(){ Jedis jedis = new Jedis("192.168.1.12",6379); //权限认证 // ...
- hdu Co-prime
题意:求出在一个区间[A,B]内与N互质的个数 . 思路: 先求出n的质因子,然后求出与N的质因子不互质的个数然后总个数减去就是.用位运算二进制表示那个因子用到过,实现容斥原理.在1到n之间是c倍数的 ...