zoukankan      html  css  js  c++  java
  • 【[CQOI2015]选数】

    这道题自然是可以反演的

    按照反演的套路我们先设出两个函数

    (F(n))表示从([L,H])中任选(N)个数的最大公约数是(n)或者(n)的倍数的情况数

    (f(n))表示从([L,H])中任选(N)个数的最大公约数是(n)的情况数

    非常显然的是

    [F(n)=sum_{n|d}f(d) ]

    [f(n)=sum_{n|d}mu(frac{d}{n})F(d) ]

    开始反演了

    首先我们发现我们求(f(k))并不好求,因为没有办法整除分块

    所一我们把(L/k,H/k)之后求(f(1))就好了

    吗?

    显然并不行啊

    我们考虑一下如果(L\%k!=0)(left lfloor frac{L}{k} ight floor imes k<L),就会使一些不在([L,H])内的数混进答案里了

    所以如果(L\%k!=0)的话,除以(k)之后再将(L+1)

    之后就是如何表示(F)

    非常显然就是

    [F(n)=(left lfloor frac{H}{n} ight floor-left lfloor frac{L-1}{n} ight floor)^N ]

    [f(1)=sum_{i=1}mu(i)F(i) ]

    (F(i))相等的用整除分块处理

    但是这道题的(H)非常大,甚至都不能线筛

    不能线筛杜教筛总可以了吧,于是就可以用(O(H^{frac{2}{3}}))的复杂度解决这道题

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<tr1/unordered_map>
    #define re register
    #define maxn 5000001
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    const int mod=1000000007;
    using namespace std::tr1;
    unordered_map<int,int> ma;
    int p[maxn>>1],f[maxn],mu[maxn];
    inline LL quick(int a,int b)
    {
        LL S=1;
        while(b) {if(b&1) S=S*a%mod;b>>=1;a=(LL)a*(LL)a%mod;}
        return S;
    }
    int N,K,L,H,M;
    int solve(int x)
    {
        if(x<=M) return mu[x];
        if(ma.find(x)!=ma.end()) return ma[x];
        int ans=1;
        for(re int l=2,r;l<=x;l=r+1)
        {
            r=x/(x/l);
            ans-=solve(x/l)*(r-l+1);
        }
        return ma[x]=ans;
    }
    int main()
    {
        scanf("%d%d%d%d",&N,&K,&L,&H);
        H/=K;
        if(L%K==0) L=L/K;
            else L=L/K+1;
        M=min(H,5000000);
        mu[1]=f[1]=1;
        for(re int i=2;i<=M;i++)
        {
            if(!f[i]) p[++p[0]]=i,mu[i]=-1;
            for(re int j=1;j<=p[0]&&p[j]*i<=M;j++)
            {
                f[p[j]*i]=1;
                if(i%p[j]==0) break;
                mu[i*p[j]]=-1*mu[i];
            }
        }
        for(re int i=1;i<=M;i++) mu[i]+=mu[i-1];
        LL ans=0;L--;
        for(re int l=1,r;l<=H;l=r+1)
        {
            if(!(L/l)) r=H/(H/l);
                else r=min(H/(H/l),L/(L/l));
            ans=(ans+quick(H/l-L/l,N)*(LL)(solve(r)-solve(l-1))%mod)%mod;
        }
        printf("%lld
    ",((ans%mod)+mod)%mod);
        return 0;
    }
    
    
  • 相关阅读:
    C#
    C#
    ssh学习笔记
    (已解决)Could not open '/var/lib/nova/mnt/*/volume-*': Permission denied
    RPCVersionCapError: Requested message version, 4.17 is incompatible. It needs to be equal in major version and less than or equal in minor version as the specified version cap 4.11.
    如何在linux下安装idea
    The system has no LUN copy license
    调整mysql数据库最大连接数
    mysql数据库编码问题
    cinder支持nfs快照
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205657.html
Copyright © 2011-2022 走看看