zoukankan      html  css  js  c++  java
  • 莫(meng)比(bi)乌斯反演--BZOJ2301: [HAOI2011]Problem b

    n<=50000个询问,每次问a<=x<=b,c<=y<=d中有多少gcd(x,y)=K的(x,y)。a,b,c,d,K<=50000。

    这大概是入门题辣。。这里记一波笔记

    当难以计算f(i)而易于计算他的反演式g(i)时,可以通过计算g(i)->反演得到f(i)。

    先放莫比乌斯函数的性质:$sum_{d|i} mu(d)=left{egin{matrix} 1,i=1\0,i>1end{matrix} ight.$,$sum_{d|i}(mu(d)*n/d)=varphi(i)$。

    反演式一:$g(i)=sum_{d|i} f(i) ------> f(i)=sum_{d|i} mu(d)g(i/d)$。

    证明:$sum_{d|i} mu(d)g(i/d)=sum_{d|i} mu(d) sum_{d_1|(i/d)} f(d_1)=sum_{d|i} sum_{d_1|(i/d)} mu(d) f(d_1)$。

    注意到$dd_1j=i$,所以对每一个$d=d_2$,$d_1=d_3$都有一个$d=d_3$,$d_1=d_2$与之对应。

    所以$上式=sum_{d|i} sum{d_1|(i/d)} f(d) mu(d_1)=sum_{d|i}  f(d) sum{d_1|(i/d)} mu(d_1)$,由莫比乌斯函数性质得$=f(i)$。

    反演式二:$g(i)=sum_{i|d} f(i) ------> f(i)=sum_{i|d} mu(d/i)g(d)$。

    证明同上,略。

    这题先容斥,变成问1<=x<=n,1<=y<=m中有多少(x,y)=K,由于(x,y)=K的充要条件是(x/K,y/K)=1,所以变成1<=x<=n/K,1<=y<=m/K中有多少(x,y)=1。

    为什么这么变呢,因为假如题目求的是f(i),表示1<=x<=n,1<=y<=m中有多少(x,y)=i,那反演式g(i)表示1<=x<=n,1<=y<=m中有多少i|(x,y),g(i)和f(i)满足反演式2。

    而明显的,$g(i)=(n/i)*(m/i)$,这里/是向下取整,所以$f(i)=sum_{i|d} mu(d/i)g(d)=sum_{i|d} mu(d/i)(n/d)(m/d)$。

    这时可以发现(n/d)和(m/d)分别只有$2sqrt(n)$和$2sqrt(m)$种取值,把他俩分别叫a和b,而随着d增大a和b会缓慢增大,可能a增大b不变,b增大a不变,也可能a,b都增大,都不变。那么数对((n/d),(m/d))最多只有$2sqrt(n)+2sqrt(m)$个,因此(n/d)*(m/d)最多只有$2sqrt(n)+2sqrt(m)$种取值。

    如果上面的i=1,那么只需要枚举这$2sqrt(n)+2sqrt(m)$个(n/d)*(m/d)的值就可以在根号时间内算出答案,因为一个(n/d)*(m/d)的值对应一段连续的d,如果i=1,就可以把连续一段莫比乌斯函数以前缀和来O(1)求和。

    入门题。

     1 #include<cstring>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 //#include<assert.h>
     5 #include<algorithm>
     6 //#include<iostream>
     7 using namespace std;
     8 
     9 int a,b,c,d,K,T;
    10 
    11 #define maxn 50011
    12 int miu[maxn],prime[maxn],lp=0,summiu[maxn]; bool notprime[maxn];
    13 void pre(int n=50001)
    14 {
    15     miu[1]=summiu[1]=1;
    16     for (int i=2;i<=n;i++)
    17     {
    18         if (!notprime[i]) {prime[++lp]=i; miu[i]=-1;}
    19         summiu[i]=summiu[i-1]+miu[i];
    20         for (int j=1;j<=lp && 1ll*i*prime[j]<=n;j++)
    21         {
    22             notprime[i*prime[j]]=1;
    23             if (i%prime[j]) miu[i*prime[j]]=-miu[i];
    24             else {miu[i*prime[j]]=0; break;}
    25         }
    26     }
    27 }
    28 
    29 #define LL long long
    30 LL solve(int p,int q)
    31 {
    32     LL ans=0;
    33     for (int i=1,last,to=min(p,q);i<=to;i=last+1)
    34     {
    35         last=min(p/(p/i),q/(q/i));
    36         ans+=1ll*(p/i)*(q/i)*(summiu[last]-summiu[i-1]);
    37     }
    38     return ans;
    39 }
    40 
    41 int main()
    42 {
    43     pre();
    44     scanf("%d",&T);
    45 while (T--)
    46 {
    47     scanf("%d%d%d%d%d",&a,&b,&c,&d,&K);
    48     printf("%lld
    ",solve(b/K,d/K)-solve((a-1)/K,d/K)-solve(b/K,(c-1)/K)+solve((a-1)/K,(c-1)/K));
    49 }
    50     return 0;
    51 }
    View Code
  • 相关阅读:
    ubuntu 15.10 64bit 下 steam无法启动
    ubuntu下使用OBS开斗鱼直播
    sql server 2008 management studio安装教程
    navicat for mysql 破解版
    nginx 重写去掉index.php
    phpstorm 注册码破解
    tp where使用数组条件,如何设置or,and
    PHPstorm 配置主题
    IE下无法保存Cookie和Session问题
    GitLab的安装及使用
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8157770.html
Copyright © 2011-2022 走看看