zoukankan      html  css  js  c++  java
  • P3455 [POI2007]ZAP-Queries

    传送门

    首先对于询问 $x,a,b$ 答案就是 $f[x]=sum_{i=1}^{a}sum_{j=1}^{b}[gcd(i,j)==x]$

    看到 $gcd(i,j)$,莫比乌斯反演走起

    设 $F[x]=sum_{i=1}^{a}sum_{j=1}^{b}[x|gcd(i,j)]$

    那么有 $F[x]=sum_{x|d}f[d]$ 且考虑 $F[x]$ 的意义发现 $F[x]=left lfloor frac{a}{x} ight floor left lfloor frac{b}{x} ight floor$

    直接反演:$f[x]=sum_{x|d}mu (d/x)F[d]=sum_{x|d}mu (d/x)left lfloor frac{a}{d} ight floor left lfloor frac{b}{d} ight floor$

    考虑枚举 $x$ 的倍数 $k$,那么:$f[x]=sum_{k}mu(k)left lfloor frac{a}{kx} ight floorleft lfloor frac{b}{kx} ight floor$

    因为 $left lfloor frac{a}{kx} ight floor=left lfloor frac{left lfloor frac{a}{x} ight floor}{k} ight floor$

    所以 $f[x]==sum_{k}mu(k)left lfloor frac{left lfloor frac{a}{x} ight floor}{k} ight floorleft lfloor frac{left lfloor frac{b}{x} ight floor}{k} ight floor$

    然后直接数论分块就好了,单次询问复杂度 $O( sqrt (n) )$

    总复杂度 $O(n sqrt (n) )$

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e6+7,M=5e4;
    int Q,n,m,d,pri[N],mu[N],sum[N],tot;
    ll f[N],F[N],ans;
    bool not_pri[N];
    void pre()
    {
        not_pri[1]=1; mu[1]=1;
        for(int i=2;i<=M;i++)
        {
            if(!not_pri[i]) pri[++tot]=i,mu[i]=-1;
            for(int j=1;j<=tot;j++)
            {
                ll t=1ll*i*pri[j]; if(t>M) break;
                not_pri[t]=1; if(!(i%pri[j])) break;
                mu[t]=-mu[i];
            }
        }
        for(int i=1;i<=M;i++) sum[i]=sum[i-1]+mu[i];
    }
    int main()
    {
        Q=read(); pre();
        while(Q--)
        {
            n=read(),m=read(),d=read();
            n/=d; m/=d; int mx=min(n,m); ans=0;
            for(int l=1,r=0;l<=mx;l=r+1)
            {
                r=min(mx, min(n/(n/l),m/(m/l)) );
                ans+=1ll*(sum[r]-sum[l-1])*(n/l)*(m/l);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Codeforces Round #271 (Div. 2) F. Ant colony 线段树
    poj 1744 tree 树分治
    HDU Shell Necklace CDQ分治+FFT
    BZOJ 1567: [JSOI2008]Blue Mary的战役地图 矩阵二维hash
    BZOJ 1042: [HAOI2008]硬币购物 容斥+背包
    HDU 6078 Wavel Sequence 树状数组优化DP
    Gym
    HDU 6058 Kanade's sum 二分,链表
    HDU 6061 RXD and functions NTT
    ZOJ 3233 Lucky Number 容斥原理
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11134696.html
Copyright © 2011-2022 走看看