zoukankan      html  css  js  c++  java
  • 洛谷P3455 [POI2007]ZAP-Queries(莫比乌斯反演)

    传送门

    设$$f(k)=sum_{i=1}^{a}sum_{j=1}^{b}[gcd(i,j)=k]$$

    $$g(n)=sum_{n|k}f(k)=lfloorfrac{a}{n} floorlfloorfrac{b}{n} floor$$

    根据莫比乌斯反演定理可以推出$$f(n)=sum_{n|k}mu(lfloorfrac{k}{n} floor)g(k)$$

    那么可以发现$ans=f(d)$

    然后用推出来的结论带进去

    $$ans=sum_{d|k}mu(lfloorfrac{k}{d} floor)g(k)$$

    枚举$lfloorfrac{k}{d} floor$设为$t$

    $$ans=sum_{t=1}^{min(lfloorfrac{a}{d} floor,lfloorfrac{b}{d} floor)}mu(t)lfloorfrac{a}{td} floorlfloorfrac{b}{td} floor$$

    对于$lfloorfrac{a}{td} floorlfloorfrac{b}{td} floor$相同的一段我们可以直接用前缀和算出答案

    总而言之就是先预处理出$mu$的前缀和然后用整除分块,那么每一次询问的复杂度就是$O(sqrt{n})$

     1 //minamoto
     2 #include<cstdio>
     3 #include<iostream>
     4 #define ll long long
     5 using namespace std;
     6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     7 char buf[1<<21],*p1=buf,*p2=buf;
     8 inline int read(){
     9     #define num ch-'0'
    10     char ch;bool flag=0;int res;
    11     while(!isdigit(ch=getc()))
    12     (ch=='-')&&(flag=true);
    13     for(res=num;isdigit(ch=getc());res=res*10+num);
    14     (flag)&&(res=-res);
    15     #undef num
    16     return res;
    17 }
    18 const int N=6e5+5;
    19 int p[N],mu[N],vis[N],m,sum[N];ll ans,lim;
    20 void init(int n){
    21     mu[1]=1;
    22     for(int i=2;i<=n;++i){
    23         if(!vis[i]) mu[i]=-1,p[++m]=i;
    24         for(int j=1;j<=m&&p[j]*i<=n;++j){
    25             vis[i*p[j]]=1;
    26             if(i%p[j]==0) break;
    27             mu[i*p[j]]=-mu[i];
    28         }
    29     }
    30     for(int i=1;i<=n;++i) sum[i]=sum[i-1]+mu[i];
    31 }
    32 int main(){
    33 //    freopen("testdata.in","r",stdin);
    34     int n,m,T,d;scanf("%d",&T);
    35     init(50000);
    36     while(T--){
    37         scanf("%d%d%d",&n,&m,&d);ans=0;
    38         lim=min(n/d,m/d);
    39         
    40         for(int l=1,r;l<=lim;l=r+1){
    41             r=min(n/(n/l),m/(m/l));
    42             ans+=1ll*(n/(l*d))*(m/(l*d))*(sum[r]-sum[l-1]);
    43         }
    44         printf("%lld
    ",ans);
    45     }
    46     return 0;
    47 }
  • 相关阅读:
    数据结构【图】—022邻接矩阵的深度和广度遍历
    第一百三十一天 how can I 坚持
    第一百三十天 how can I 坚持
    第一百二十九天 how can I坚持
    第一百二十八天 how can i 坚持
    第一百二十七天 how can I 坚持
    第一百二十六天 how can I 坚持
    第一百二十五天 how can I坚持
    第一百二十四天 how can I坚持
    第一百二十三天 how can I 坚持
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9688653.html
Copyright © 2011-2022 走看看