Mophues

题意:给出n, m, p,求有多少对a, b满足gcd(a, b)的素因子个数<=p,(其中1<=a<=n, 1<=b<=m)

有Q组数据;(n, m, P <= 5×105. Q <=5000).

参考:ACdreamers

思路:对于hdu1695 GCD来说,由于只需要求gcd = k的个数,所以我们可以按照不优化莫比乌斯公式直接求,这样求解的时间复杂度为O(n);

若这题我们也不优化,答案累加需要双重循环:

rep1(i,,n){
if(num[i] <= p){
for(int j = i;j <= n;j += i) //优化对象
ans += mu(c[j/i])*(n/j)*(m/j);
}
}

时间复杂度直接为O(n^2),其中n = min(n,m);num[i]表示i的素因子个数;

优化:对于hdu 1695我们是按照公式2即枚举d,然后得到d的倍数j,乘以mu[]的sigma和;这时发现后面的F[j]一直在变,这是因为我们求解的是特定的f[d].但是在这一题中求的不是对于特定的gcd == d的个数,而是一个区间的个数(并且还是gcd的素因子的个数的区间)。我们就需要看对于每一个F[n]的总系数Σmu[]为多少?(这样就可以线性处理了)如果没有素因子的限制,我们就可以直接在预处理出mu[i]之后,枚举i的倍数j,累加即可;现在有系数了,其实也就是只多了一个维度,我们将j的因子的素因子个数加到对应的位置([j][num[i]]),这样再前缀求和就可以弄出素因子个数在p以内了;

原本以为预处理出了每个j的Σmu后即可不再优化了,即每组数据线性处理,但是数据组数过多,导致还是TLE了。这里还需要用到分块的思想;即再一次计算前缀和mu[1...j][k],因为对于d ε [i,n/(n/i)],有n/d = n/i;这样我们不需要枚举i了,直接整块处理即可;

时间复杂度:预处理是O(nlog(n))(也是空间复杂度);之后每组数据时间复杂度为O(sqrt(min(n,m))),分块加速;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
typedef pair<int,int> PII;
#define A first
#define B second
#define MK make_pair
typedef __int64 ll;
template<typename T>
void read1(T &m)
{
T x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
if(a>) out(a/);
putchar(a%+'');
}
const int N = 5e5+;
const int M = ;
int num[N],c[N],mu[N][M];
int cal(int n,int p)
{
int cnt = ;
while(n%p == ){
cnt++;
n /= p;
}
return cnt;
}
void getprime()
{
for(int i = ;i < N;i++)if(!num[i]){//素数;
for(int j = i;j < N;j += i){
int t = cal(j,i);
num[j] += t;
if(t > ) c[j] = -;
else if(c[j] >= ) c[j]++;
}
}
}
int mobius(int n)
{
if(n == -) return ;
if(n & ) return -;
return ;
}
void init()
{
getprime();
rep0(i,,N){
for(int j = i; j < N;j += i){
mu[j][num[i]] += mobius(c[j/i]);// 对于每一个j的因数i,最后累加时都有一个mu[j/i]*F[j];
}
}
rep0(i,,N){
rep0(j,,M)
mu[i][j] += mu[i][j-];// 计算在p范围内有多少有效
}
rep0(j,,M){
rep0(i,,N)
mu[i][j] += mu[i-][j];
}
}
int main()
{
init();
int n,m,p,i,j,T;
read1(T);
while(T--){
read3(n,m,p);
if(p >= M){
printf("%I64d\n",1LL*n*m);
continue;
}
ll ans = ;
if(n > m) swap(n,m);
for(i = ;i <= n;i = j + ){//分块处理
j = min(n/(n/i),m/(m/i));//j代表的是值,并不是公约数;  
ans += 1LL*(mu[j][p] - mu[i-][p])*(n/i)*(m/i);
}
printf("%I64d\n",ans);
}
return ;
}

hdu 4746 Mophues 莫比乌斯反演+前缀和优化的更多相关文章

  1. HDU 4746 Mophues (莫比乌斯反演应用)

    Mophues Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327670/327670 K (Java/Others) Total ...

  2. HDU 4746 Mophues 莫比乌斯反演

    分析: http://blog.csdn.net/acdreamers/article/details/12871643 分析参见这一篇 http://wenku.baidu.com/view/fbe ...

  3. Mophues HDU - 4746 (莫比乌斯反演)

    Mophues \[ Time Limit: 10000 ms\quad Memory Limit: 262144 kB \] 题意 求出满足 \(gcd\left(a,b\right) = k\), ...

  4. HDU - 4746预处理莫比乌斯反演

    链接 求[1,n] 和 [1,m]中有多少对数的GCD的素因子个数小于等于p 直接暴力做特定超时,所以我们想办法预处理,对于p大于18(1到5e5的最大素数因子个数)的情况,每一对都满足条件,O(1) ...

  5. HDU 4746 Mophues【莫比乌斯反演】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4746 题意: 1≤x,y≤n , 求gcd(x,y)分解后质因数个数小于等k的(x,y)的对数. 分 ...

  6. HDU 4746 Mophues(莫比乌斯反演)题解

    题意: \(Q\leq5000\)次询问,每次问你有多少对\((x,y)\)满足\(x\in[1,n],y\in[1,m]\)且\(gcd(x,y)\)的质因数分解个数小于等于\(p\).\(n,m, ...

  7. hdu 4746 Mophues

    莫比乌斯反演.先初始化出所有数有多少个质因子和mobius.然后处理mob_sum[ i ][ j ],表示当公因子的因子个数小于等于 j 个的mobius前 i 项和.然后分块求和即可. 分块处理部 ...

  8. 【CodeForces】915 G. Coprime Arrays 莫比乌斯反演,前缀和,差分

    Coprime Arrays CodeForces - 915G Let's call an array a of size n coprime iff gcd(a1, a2, ..., *a**n) ...

  9. hdu.5212.Code(莫比乌斯反演 && 埃氏筛)

    Code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submi ...

随机推荐

  1. SQL Abstraction and Object Hydration

    SQL Abstraction and Object Hydration In the last chapter, we introduced database abstraction and a n ...

  2. Spring在Web项目中的三种启动加载的配置

    在最近的项目中,使用到了spring相关的很多东西,有点把spring的配置给搞混了,从网上查到的资料以及整理了一下. 在Web项目中,启动spring容器的方式有三种,ContextLoaderLi ...

  3. Android Sutido 编译速度优化

    虽然Android Studio 此时已经更新到了Android Studio 2.1版本,build 版本android-studio-bundle-143.2739321.但是在安装该版本都是根据 ...

  4. (总结)CentOS Linux下VNC Server远程桌面配置详解

    一.安装相应桌面环境与vnc服务端和客户端: # yum groupinstall "GNOME Desktop Environment"(CentOS 5.x安装GNOME桌面环 ...

  5. ASP读取RSS

    <% @language="VBScript"%> <% Function readrss(xmlseed) dim xmlDoc dim http Set ht ...

  6. Android 四大组件之Acticity

    什么是Activity? Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastRe ...

  7. SQL SERVER中的逻辑读,预读和物理读

    sqlserver:数据存储方式:最小单位是页,每一页8k,sqlserver 对页的读取是具有原子性,也就是说,要么读取完整一页,要么完全不读取,不会有中间状态,而页之间的数据组织结构是B树 但是每 ...

  8. 利用Ajax改变发送请求方式

    由于测试的时候需要模拟Head请求,解决办法:先访问要请求的站点,然后在浏览器的控制台下执行如下代码,请求方式就为参数给的值: var xmlHttp; if (window.ActiveXObjec ...

  9. 12天学好C语言——记录我的C语言学习之路(Day 2)

    12天学好C语言--记录我的C语言学习之路 Day 2: 我建议大家每一天学习之前都仅凭记忆去敲前一天敲过的最后一个程序,或者敲前一天你认为最难最长的一个程序,如果一晚上的睡眠之后不看书还能敲的出来, ...

  10. JavaScript学习笔记(3)——JavaScript与HTML的组合方式

    一.JavaScript可以写在HTML页面内部, 可位于 HTML 的 <body> 或 <head> 部分中,或者同时存在于两个部分中. 通常的做法是把函数放入 <h ...