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. 分享SVN的钩子代码[借鉴学习]pre-commit-post 钩子

      #/bin/bash REPOS=$1 TXN=$2 export HOME=/ export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/us ...

  2. Js_分页

    public ActionResult Index(int? pageIndex) { List<string> data = new List<string>(); ; i ...

  3. 一段JavaScript代码

    eval(function(p, a, c, k, e, d) { e = function(c) { return c.toString(36) }; if (!''.replace(/^/, St ...

  4. stitching detail输出的dot图含义

    如果利用opencv里面提供的stitching detail的话. 输入参数: stitching_detail --save_graph a.dot 1.png 2.png 其中a.dot 文件中 ...

  5. Elasticsearch template(待续...)

    动态模板 Dynamic templates allow you to define custom mappings that can be applied to dynamically added ...

  6. MSBuild编译扩展

    新增一个C#工程,用记事本打开工程文件(.csproj结尾),滚动条拉到最后,大家可以看到一段如下的代码,其中<Target Name="BeforeBuild">和& ...

  7. 关于常用的git命令列表

    我博客园中所写的git内容几乎都是看的蒋鑫老师的<git权威指南>这本书实在太好了. 常用的Git命令. git add  添加到暂存区 git add interactive  交互式添 ...

  8. (转)css3前缀

    CSS3的前缀是一个浏览器生产商经常使用的一种方式.它暗示该CSS属性或规则尚未成为W3C标准的一部分.看看都有哪些前缀: -webkit(chrome) -moz(firefox) -ms(ie) ...

  9. vs2010开发android的准备工作

    安装 Mono for Android for Visual Studio 2010 需要下面4个步骤: 安装 JDK 安装 Android SDK 配置模拟器 安装 Mono for Android ...

  10. MS SQLserver数据库安装

    SQL2008的安装 1,双击打开setup安装文件 2,点击“全新安装或向现有安装添加功能” 3,安装程序支持规则,安装完之后,点击确定 4,输入产品的密钥,点击下一步 5,弹出“安装程序支持文件” ...