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


    题意:求(1leq i leq N,1leq j leq M,gcd(i,j))的质因子个于等于p的对数。
    分析:加上了对质因子个数的限制。
    (f(d):[gcd(i,j)=d]) , (F(d):[d|gcd(i,j)]) ,k是满足质因子<=p的数。
    (ans = sum_{k}f(k) = sum_{k}sum_{k|d}u(frac{d}{k})lfloor frac{N}{d} floor lfloorfrac{M}{d} floor = sum_{d}lfloor frac{N}{d} floor lfloorfrac{M}{d} floorsum_{k|d}u(frac{d}{k}))
    (sum_{k|d}u(frac{d}{k}))可以预处理得到。
    由于限制了质因子的个数,并且我们还想用分块的方法求出最后答案,于是设(sum(a,b):sum_{i=1}^{a}sum_{k|i且k质因子个数leq j}u(frac{i}{k}))。在打出莫比乌斯函数表后,可以在预处理出(sum(a,b)表),由于1e6以内的数质因子个数不会超过20,因此第二维开到20即可。
    那么计算结果时可以分块加速求出ans的值。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn=5e5+5;
    bool vis[maxn];
    int prime[maxn],mu[maxn];
    int sum[maxn][20];
    int pricnt[maxn];
    void init(){
        memset(vis,false,sizeof(vis));
        mu[1] = 1;
        prime[0] = 0;
        int cnt=0;
        for(int i=2;i<maxn;++i){
            if(!vis[i]){
                mu[i] = -1;
                pricnt[i] = 1;
                prime[++cnt] = i;
            }
            for(int j=1;j<=cnt;++j){
                if(i*prime[j] >= maxn)  break;
                pricnt[i*prime[j]] = pricnt[i]+1;
                vis[i*prime[j]] = true;
                if(i % prime[j]){
                    mu[i*prime[j]] = -mu[i];
                }
                else{
                    mu[i*prime[j]] = 0;
                    break;
                }
            }
        }
    }
    
    void prepare(){
        for(int i=1;i<maxn;++i){
            for(int j= i;j<maxn;j+=i){
                sum[j][pricnt[i]] += mu[j/i];
            }
        }
        for(int i=1;i<maxn;++i){
            for(int j =0;j<20;++j){
                sum[i][j] +=sum[i-1][j];
            }
        }
        for(int i=1;i<maxn;++i){
            for(int j=1;j<20;++j){
                sum[i][j] +=sum[i][j-1];
            }
        }
    }
    
    LL gao(LL n,LL m,LL p)      //枚举p
    {
        LL ans = 0;
        for(int i=1,j;i<=n;i=j+1){
            j = min(n/(n/i),m/(m/i));
            ans += (sum[j][p]-sum[i-1][p])*(n/i)*(m/i);
        }
        return ans; 
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        init();
        prepare();
        LL N,M,p;
        int T; scanf("%d",&T);
        while(T--){
            scanf("%lld %lld %lld",&N, &M,&p);
            LL res=0;
            if(p>=20){
                res = N*M;
            }
            else{
                if(N>M) swap(N,M);
                res = gao(N,M,p);
            }
            printf("%lld
    ",res);
        } 
        return 0;
    }
    
    为了更好的明天
  • 相关阅读:
    遇到一个php解析错误
    wndows netsh winsock reset
    javascript 阻塞
    ci 文件类型错误xlsx
    input限制整数
    canvas 时钟转动
    JS实现别踩白块游戏
    本地存储技术localStorage
    JavaScript事件
    JavaScript实现放大镜效果
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9542685.html
Copyright © 2020-2023  润新知