• 洛谷 P2522 [HAOI2011]Problem b(莫比乌斯反演+容斥)


    题目大意:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
    数据范围:100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000


    题解

    询问可以用容斥来解决,就转换成了那个题了:1<=x<=n,1<=y<=m
    和上次那个题差不多,还是推公式。
    传送门
    预处理莫比乌斯函数前缀和,可以根号处理询问,因为那一坨只有n个取值。
    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define ll long long
    using namespace std;
    int mu[50001];
    int vis[50001];
    int prime[50001];
    int cnt;
    void init(int n){
        mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!vis[i]){
                prime[++cnt]=i;
                mu[i]=-1;
            }
            for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
                int k=i*prime[j];
                vis[k]=1;
                if(i%prime[j]){
                    mu[k]=-mu[i];
                }
                else{
                    mu[k]=0;
                    break;
                }
            }
            mu[i]+=mu[i-1];
        }
    }
    inline ll solve(int n,int m,int k){
        n/=k;
        m/=k;
        ll ans=0;
        int lim=min(n,m);
        for(int i=1,j;i<=lim;i=j+1){
            j=min(n/(n/i),m/(m/i));
            ans+=(ll)(n/i)*(ll)(m/i)*(ll)(mu[j]-mu[i-1]);
        }
        return ans;
    }
    int t;
    int a,b,c,d,k;
    int main(){
        init(50000);
        scanf("%d",&t);
        while(t--){
            scanf("%d %d %d %d %d",&a,&b,&c,&d,&k);
            printf("%lld
    ",solve(b,d,k)+solve(a-1,c-1,k)-solve(a-1,d,k)-solve(b,c-1,k));
        }
        return 0;
    }
  • 相关阅读:
    【BJOI2018】求和
    【洛谷P1613】跑路
    【NOI2001】食物链
    【NOI2002】银河英雄传说
    【POJ1456】Supermarket
    【NOIP2013】货车运输
    【CH#56C】异象石
    【POJ3417】Network
    【APIO2010】巡逻
    【CH6201】走廊泼水节
  • 原文地址:https://www.cnblogs.com/stone41123/p/7581262.html
Copyright © 2020-2023  润新知