hdu 4746 Mophues 质因子数量小于p

推式子

设: n u m [ x ] num[x] 表示 x x 唯一分解后所有质因子指数之和

a n s = i = 1 n j = 1 m [ n u m [ gcd ( i , j ) ] < = p ] \begin{aligned} ans= \sum_{i=1}^{n}\sum_{j=1}^{m}[num[\gcd(i,j)]<=p] \end{aligned}

我们发现 n , m < = 5 1 0 5 n,m<=5*10^{5} ,故 gcd ( i , j ) < = 5 1 0 5 \gcd(i,j)<=5*10^{5}
所以 gcd ( i , j ) \gcd(i,j) 最多有18个质因子 ( 2 18 = 262144 < 5 1 0 5 ) \quad(2^{18}=262144<5*10^{5})
如果 p > 18 p>18 ,那么所有对都可以,答案为 n m n*m
对于 p < = 18 p<=18 ,先考虑:

f ( d ) = i = 1 n j = 1 m [ gcd ( i , j ) = = d ] \begin{aligned} f(d)= \sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)==d] \end{aligned}

F ( n ) = n d f ( d ) F(n)=\sum_{n \mid d}f(d) ,根据莫比乌斯反演有:

f ( d ) = d t μ ( t d ) F ( t ) = d t μ ( t d ) n t m t \begin{aligned} f(d)=\sum_{d \mid t}\mu(\frac{t}{d})F(t)= \sum_{d \mid t}\mu(\frac{t}{d})\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor \end{aligned}

所以:

a n s = n u m [ d ] < = p d t μ ( t d ) n t m t = n u m [ d ] < = p T = 1 min ( n , m ) μ ( T d ) n T m T \begin{aligned} ans= \sum_{num[d]<=p}\sum_{d \mid t}\mu(\frac{t}{d})\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor= \sum_{num[d]<=p}\sum_{T=1}^{\min(n,m)}\mu(\frac{T}{d})\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor \end{aligned}

a n s = T = 1 min ( n , m ) n T m T n u m [ d ] < = p μ ( T d ) \begin{aligned} ans= \sum_{T=1}^{\min(n,m)}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{num[d]<=p}\mu(\frac{T}{d}) \end{aligned}

前面的可以分块解决,后面的前缀和处理

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T>
void out(T x) { cout << x << endl; }
ll fast_pow(ll a, ll b, ll p) {ll c = 1; while(b) { if(b & 1) c = c * a % p; a = a * a % p; b >>= 1;} return c;}
ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) {x = 1; y = 0; return a; } ll gcd = exgcd(b, a % b, y, x); y-= a / b * x; return gcd; }
const int N = 5e5 + 5;
int prime[N], mu[N], num[N], tot;
bool mark[N];
ll nump[N][20];
void get_mu()
{   
    memset(nump, 0, sizeof(nump));
    mu[1] = 1;
    num[1] = 0;
    mark[1] = mark[0] = true;
    tot = 0;
    for(int i = 2; i < N; i ++)
    {
        if(!mark[i])
        {
            prime[tot ++] = i;
            mu[i] = -1;
            num[i] = 1;
        }
        for(int j = 0; j < tot && i * prime[j] < N; j ++)
        {
            mark[i * prime[j]] = true;
            num[i * prime[j]] = num[i] + 1;
            if(i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }
    for(int i = 1; i < N; i ++)
        for(int j = i; j < N; j += i)
            nump[j][num[i]] += mu[j / i];
    for(int i = 1; i < N; i ++)
        for(int j = 1; j < 19; j ++)
            nump[i][j] += nump[i][j - 1];
    for(int i = 1; i < N; i ++)
        for(int j = 0; j < 19; j ++)//gcd为1,num[gcd]=0
            nump[i][j] += nump[i - 1][j];
}
ll cal(ll n, ll m, ll p)
{
    if(n > m)
        swap(n, m);
    ll ans = 0;
    for(ll i = 1, j = 1; i <= n; i = j + 1)
    {
        j = min(n / (n / i), m / (m / i));
        ans += (n / i) * (m / i) * (nump[j][p] - nump[i - 1][p]);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    get_mu();
    int t;
    cin >> t;
    while(t --)
    {
        ll n, m, p;
        cin >> n >> m >> p;
        if(p > 18)
        {
            cout << n * m << endl;
            continue;
        }
        cout << cal(n, m, p) << endl;
    }
}

原创文章 83 获赞 6 访问量 2760

猜你喜欢

转载自blog.csdn.net/qq_43101466/article/details/102574856