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;
    }
    
    
  • 相关阅读:
    es6 类
    set/ weakset/ map/ weakmap
    async/await
    生成函数
    数组的操作
    解决异步(重点promise函数)
    迭代器
    遍历
    symbol 数据类型
    es6.代理 proxy
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205657.html
Copyright © 2011-2022 走看看