zoukankan      html  css  js  c++  java
  • bzoj2820--莫比乌斯反演

    题目大意:

    给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对。

    推导:

    设n<=m

    ans= 

         =

    由于gcd(i,j)==1等价于

    ans=

          =

    令 T=pt

    则ans=

    设f(T)=

    则f(T)可以用线性筛O(n)预处理出来。

    ans=

    分块就可以了。总时间复杂度为

    具体看代码。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define N 10000001
    struct node{
        int x,y;
    }a[10001];
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        if(p1==p2){
            p2=(p1=buf)+fread(buf,1,100000,stdin);
            if(p1==p2)return EOF;
        }
        return *p1++;
    }
    inline void read(int& x){
        char c=nc(),b=1;
        for(;!(c>='0'&&c<='9');c=nc());
        for(x=0;c>='0'&&c<='9';x=x*10+c-48,c=nc());x*=b;
    }
    int len;
    char c[20];
    inline void print(long long x){
        if(!x){
            putchar('0');
            putchar('
    ');
            return;
        }
        for(len=0;x;x/=10)c[++len]=x%10;
        for(;len;len--)putchar(c[len]+'0');
        putchar('
    ');
    }
    inline int Min(int x,int y){
        return x<y?x:y;
    }
    int p[N],tot,t,i,j,k,n,m,mu[N],y,T,ma,x;
    long long ans,f[N];
    bool v[N];
    int main()
    {
        read(T);
        for(i=1;i<=T;i++){
            read(a[i].x);read(a[i].y);
            if(a[i].y<a[i].x){t=a[i].x;a[i].x=a[i].y;a[i].y=t;}
            if(a[i].x>ma)ma=a[i].x;
        }
        mu[1]=1;
        for(i=2;i<=ma;i++){
            if(!v[i]){
                p[++tot]=i;
                mu[i]=-1;
            }
            for(j=1;j<=tot&&p[j]*i<=ma;j++){
                v[i*p[j]]=1;
                if(i%p[j])mu[i*p[j]]=-mu[i];else{
                    mu[i*p[j]]=0;
                    break;
                }
            }
        }
        for(i=1;i<=tot;i++)f[p[i]]++;
        for(i=2;i<=ma;i++)
        for(j=1;p[j]*i<=ma;j++)
        f[i*p[j]]+=mu[i];
        for(i=2;i<=ma;i++)f[i]+=f[i-1];
        for(x=1;x<=T;x++){
            i=1;ans=0;
            while(i<=a[x].x){
                j=Min(a[x].x/(a[x].x/i),a[x].y/(a[x].y/i));
                ans+=(f[j]-f[i-1])*(a[x].x/i)*(a[x].y/i);
                i=j+1;
            }
            print(ans);
        }
        return 0;
    }
    bzoj2820
  • 相关阅读:
    nethogs 实时查看进程使用流量情况。
    Bash 使用技巧
    Linux源代码编译安装tree命令
    【字体区别】Serif和Sans Serif
    MySQL数据库恢复的经历。
    Linux常用命令
    关于一机多区的可行性分析。
    记一次node节点异常排查
    kube-prometheus部署
    认证、授权与准入控制
  • 原文地址:https://www.cnblogs.com/gjghfd/p/6159207.html
Copyright © 2011-2022 走看看