• bzoj 2301: [HAOI2011] Problem b


    Time Limit: 50 Sec  Memory Limit: 256 MB
    Submit: 2833  Solved: 1256
    [Submit][Status][Discuss]

    Description

    对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

    Input

    第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k

    Output

    共n行,每行一个整数表示满足要求的数对(x,y)的个数

    Sample Input

    2
    2 5 1 5 1
    1 5 1 5 2

    Sample Output

    14
    3

    HINT

    100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000

    题解:

      首先先放个PoPoQQQ的ppt其次再来份题解。(题解中的容斥定理把c和b写反了,无视就好)

      总结一下,莫比乌斯反演有两种形式

      形式一:

                

      形式二:

              

      本题用到的是第二种形式,题目要求求x∈[a,b],y∈[c,d]。x和y满足gcd(x,y)==k的x和y的数对数。

      令f(i)为x∈[1,N],y∈[1,M],gcd(x,y)==i 的(x,y)数对数。

      令F(i)为x∈[1,N],y∈[1,M],i|gcd(x,y) 的(x,y)数对数。

      可以感觉,a和c的限制有些不好处理,不妨先忘掉a,c的限制。再看形式二,考虑f(i)与F(i)的关系,f(i)是gcd(x,y)==i,F(i)是gcd(x,y)==t*i(t∈Z),所以F(i)=sigma(f(d))(i|d),所以f(i)与F(i)正好满足形式二的第一个,可以利用莫比乌斯反演用F(i)表示f(i)。而F[i]=[N/i]*[M/i]  ([]表示向下取整)

      再考虑a和c的限制,设g(x,y,k)表示[1,x],[1,y] gcd(x1,y1)==k的对数,这个式子其实等价于g(x/k,y/k,1)。

      再有容斥原理可得:Ans=g(b/k,d/k,1)-g((a-1)/k,d/k,1)-g(c/k,b/k,1)+g((a-1)/k,(c-1)/k,1),对于每个g(,,)我们都可以用f()来求。

      O(n)的复杂度不足以解决此题,还有一个O(sqrt(n))的优化,具体看ppt或题解,讲的很清楚。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<vector>
     8 #include<queue>
     9 using namespace std;
    10 typedef long long LL; 
    11 const LL maxn=50000; 
    12 LL mu[maxn],prime[maxn],sum[maxn],tot,N;
    13 bool not_prime[maxn];
    14 LL a,b,c,d,k,ANS;
    15 inline void pre(){
    16     memset(not_prime,false,sizeof(not_prime));
    17     mu[1]=1;
    18     for(LL i=2;i<=maxn;i++){
    19         if(not_prime[i]==false){
    20             prime[++tot]=i;
    21             mu[i]=-1;
    22         }
    23         for(LL j=1;j<=tot;j++){
    24             if(i*prime[j]>maxn) break;
    25             not_prime[prime[j]*i]=true;
    26             if(i%prime[j]==0){
    27                 mu[prime[j]*i]=0;
    28                 break;
    29             }
    30             else mu[prime[j]*i]=-mu[i];
    31         }
    32     }
    33 }
    34 inline LL solve(LL N,LL M){
    35     LL ans=0;
    36     if(N>M) swap(N,M);
    37     for(LL i=1,la=0;i<=N;i=la+1){
    38         la=min(N/(N/i),M/(M/i));
    39         ans+=(sum[la]-sum[i-1])*(N/i)*(M/i);
    40     }
    41     return ans;
    42 } 
    43 int main(){
    44 //    freopen("b.in","r",stdin);
    45 //    freopen("b.out","w",stdout);
    46     pre();
    47     sum[0]=0;
    48     for(LL i=1;i<=maxn;i++){
    49         sum[i]=sum[i-1]+mu[i];
    50     }
    51     scanf("%d",&N);
    52     while(N--){
    53         scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
    54         ANS=solve(b/k,d/k)-solve((a-1)/k,d/k)-solve(b/k,(c-1)/k)+solve((a-1)/k,(c-1)/k);
    55         printf("%lld
    ",ANS);
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    人脸识别活体检测测试案例
    网络相关配置
    DOS基础整理
    [转载]EXTJS学习
    [转载]JS定时器例子讲解
    [转载]JS定时器例子讲解
    如何设置网页自动刷新(JSP,JS,HTML)
    如何设置网页自动刷新(JSP,JS,HTML)
    18岁以下严禁进入
    18岁以下严禁进入
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5264643.html
Copyright © 2020-2023  润新知