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

来源:互联网 发布:用递归算法计算斐波拉 编辑:程序博客网 时间:2024/06/03 14:08

题意:定义x,p:假如x的所有质因数的个数小于等于p,则称x is a lucky number of P.然后问你1<=x<=n 

1<=y<=m中,有多少对(x,y)满足gcd(x,y)is a lucky number of P.题意:定义x,p:假如x的所有质因数的个数小于等于p,则称x

题解:这道题和之前做的gcd很像,我们可以定义一个函数F(x)表示x有多少个质因数,假设我们当前求gcd(x,y)=d,可以等价于求gcd(x,y)=1 1<=x<=n/d && 1<=y<=m/d...这在之前的题目中已经说明过了,我们仍然可以仿照之前的做法,令f(d)为gcd(x,y)=d的对数,g(d)为gcd(x,y)=d的倍数的个数。显而易见,g(d)可以无脑算出,答案是g(d)=[n/d][m/d]([]为向下取整),然后我们可以利用莫比乌斯反演定理,在O(n)的时间内求出每个值的贡献,然而对于这道题来说是超时的,因此,我们仍然考虑分块,这道题并不想之前呢样简单的求一波前缀和就可以的。

因为涉及到素因数的个数,故要开一个二维的前缀和dp[d][p]:表示质因数个数<=p时对g(d)的贡献系数。

#include<map>     #include<stack>            #include<queue>            #include<vector>    #include<string>  #include<math.h>            #include<stdio.h>            #include<iostream>            #include<string.h>            #include<stdlib.h>    #include<algorithm>   #include<functional>    using namespace std;typedef long long  ll;#define inf  1000000000       #define mod 1000000007             #define maxn  560050  #define lowbit(x) (x&-x)            #define eps 1e-9  ll a[maxn] = { 1,1 }, b[maxn], mu[maxn], cnt, num[maxn], dp[maxn][20];void init(){ll i, j;mu[1] = 1;for (i = 2;i<maxn;i++){if (a[i] == 0)b[++cnt] = i, mu[i] = -1, num[i] = 1;for (j = 1;j <= cnt && i*b[j] <= maxn;j++){a[b[j] * i] = 1; num[b[j] * i] = num[i] + 1;if (i%b[j] == 0){mu[b[j] * i] = 0;break;}elsemu[b[j] * i] = -mu[i];}}for (i = 1;i <= maxn;i++)for (j = i;j <= maxn;j += i)dp[j][num[i]] += mu[j / i];for (i = 0;i <= maxn;i++)for (j = 1;j <= 19;j++)dp[i][j] += dp[i][j - 1];for (i = 1;i <= maxn;i++)for (j = 0;j <= 19;j++)dp[i][j] += dp[i - 1][j];}int  main(void){init();ll T, i, x, y, k, p, last;scanf("%lld", &T);while (T--){ll sum = 0;scanf("%lld%lld%lld", &x, &y, &p);if (x > y)  swap(x, y);p = min(p, 18ll);for (i = 1, last = 0;i <= x;i = last + 1){last = min(x / (x / i), y / (y / i));sum += (ll)(dp[last][p] - dp[i-1][p])*(x / i)*(y / i);}printf("%lld\n", sum);}return 0;}