zoukankan      html  css  js  c++  java
  • BZoj 2301 Problem b(容斥定理+莫比乌斯反演)

    2301: [HAOI2011]Problem b

    Time Limit: 50 Sec  Memory Limit: 256 MB
    Submit: 7732  Solved: 3750
    [Submit][Status][Discuss]

    Description

    对于给出的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

    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

    题解:简化为计算a/k<=x<=b/k,c/k<=y<=d/k满足gcd(x,y)=1的x,y有多少对;cal(n,m)代表1<=x<=n,1<=y<=m满足gcd(x,y)=1的(x,y)对数,则根据容斥定理:

    small {color{Red} ans=frac{cal(b,d)-cal(a-1,d)}{a<=x<=b,1<=y<=b}-frac{cal(b,c-1)-cal(a-1,c-1))}{a<=x<=b,1<=y<=c}}

    #include<iostream>
    #include<stdio.h>
    #define ll long long
    using namespace std;
    const ll N=50007;
    ll prime[N],mu[N];
    bool mark[N];
    void getmu()
    {
            mu[1]=1;
            int cnt=0;
            for(int i=2;i<=N;i++){
                    if(!mark[i])
                            prime[cnt++]=i,mu[i]=-1;
                    for(int j=0;j<cnt&&i*prime[j]<=N;j++){
                            mark[i*prime[j]]=1;
                            if(i%prime[j]){
                                    mu[i*prime[j]]=-mu[i];
                            }else{
                                    mu[i*prime[j]]=0;break;
                            }
                    }
                    mu[i]+=mu[i-1];//后面不会再用到mu[i],所以可以直接记为前缀和
            }
    }
    ll cal(ll n,ll m){
            if(n>m)
                    swap(n,m);
            ll ans=0;
            for(ll l=1,r;l<=n;l=r+1){
                    r=min(n/(n/l),m/(m/l));
                    ans+=(mu[r]-mu[l-1])*(n/l)*(m/l);
            }
            return ans;
    }
    int main()
    {
            int T;
            ll a,b,c,d,k;
            getmu();
            scanf("%d",&T);
            while(T--){
                    scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
                    a=(a-1)/k,b=b/k,c=(c-1)/k,d=d/k;
                    printf("%lld
    ",cal(b,d)-cal(a,d)-(cal(c,b)-cal(c,a)));
            }
            return 0;
    }
    
  • 相关阅读:
    git
    界面编程与视图(View)组件
    genymotion的安装
    210中断故障分析
    6410/210按键中断编程
    2440按键中断编程
    中断处理流程深度剖析
    scrapy 写文件进行debug调试
    scrapy 爬虫中间件-offsite和refer中间件
    scrapy文件管道
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/10262674.html
Copyright © 2011-2022 走看看