• [JXOI2018]游戏 (线性筛,数论)


    [JXOI2018]游戏



    $ solution: $

    这一道题的原版题面实在太负能量了,所以用了修改版题面。

    这道题只要仔细读题,我们就可以将题目的一些基本性质分析出来:首先我们定义:对于某一类都可以被x整除的数(要在 $ [l,r] $ 之内),若x也在我们的 $ [l,r] $ 之内且x不能被 $ [l,r] $ 内任意其它数整除,我们称这类数为关联数且x为特殊数,(显然:当九条可怜查了x这间办公室后,所有以x为特殊数的关联数都不需要再检查了!)(而且:这一类以x为特殊数的关联数,只有且只要当x被检查后,这一类数都不需要检查了!)

    然后我们可以将 $ [l,r] $ 内所有的数,都分为以不同数为特殊数的关联数。然后我们发现只有且只要当所有的特殊数都被检查后,整个 $ [l,r] $ 就都不需要检查了(这个可以根据上面括号里的第二条性质推出来)。所以我们用线性筛把这一类特殊数筛出来(我们不难发现对于一个数x,如果它除以它的最小因子(得到比它小的最大的约数),如果它不在 $ [l,r] $ 内,则说明它是一个特殊数)。然后我们可以枚举最后一个特殊数在操作序列中出现的位置(假设现在枚举到i),于是这个序列的后面一部分(即n-i个数)就无关紧要了,这相当于我们从tot(假设 $ [l,r] $ 中不是特殊数的有tot个)个非特殊数中取出n-i个数随便排列,然后i之前特殊数和非特殊数也可以随便排列。

    于是我们得出答案就是:

    $ ans=sum_{i=tot}^n i imes tot imes C binom{n-i}{n-tot} imes (n-i)! imes (i-1)! $

    按顺序:(枚举最后一个特殊数的位置)(最后一个特殊数数在i结束,会有i的贡献)(这个位置可以是tot里的任意一个特殊数)(从剩下的非组合数n-tot个中取出n-i个放在i后面)(后面的n-i个非特殊数数可以随便排列)(前面的i-1个数也可以随便排列)

    于是我们可以暴力求阶乘,阶乘逆元,还有线性筛即可。



    $ code: $

    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    
    #define ll long long
    #define db double
    #define inf 0x7fffffff
    #define rg register int
    
    using namespace std;
    
    const int mod=1e9+7;
    
    int l,r,n,tot,ans;
    int ni[10000005];
    int jc[10000005];
    int pr[10000005];
    int use[10000005];
    
    inline int qr(){
        char ch;
        while((ch=getchar())<'0'||ch>'9');
        int res=ch^48;
        while((ch=getchar())>='0'&&ch<='9')
            res=res*10+(ch^48);
        return res;
    }
    
    inline int ksm(ll x,int y,int p){
        ll res=1;
        while(y){
            if(y&1)(res*=x)%=p;
            (x*=x)%=p; y>>=1;
        }return res;
    }
    
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        l=qr(); r=qr(); n=r-l+1; jc[0]=1;
        for(rg i=1;i<=r;++i)
            jc[i]=(ll)jc[i-1]*i%mod;
        ni[r]=ksm(jc[r],mod-2,mod);
        for(rg i=r;i;--i)
            ni[i-1]=(ll)ni[i]*i%mod;
        if(l==1){printf("%lld
    ",(ll)jc[r]*(n+1)%mod*ksm(2,mod-2,mod)%mod);return 0;}
        for(rg i=2;i<=r;++i){
            if(!use[i])use[i]=i,pr[++tot]=i;
            for(rg j=1;j<=tot;++j){
                if(pr[j]*i>r)break;
                use[pr[j]*i]=pr[j];
                if(!(i%pr[j]))break;
            }
        } tot=0;
        for(rg i=l;i<=r;++i)if(i/use[i]<l)++tot;
        for(rg i=tot;i<=n;++i){
            (ans+=(ll)tot*jc[n-tot]%mod*jc[i]%mod*ni[i-tot]%mod)%=mod;
        }printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    数制
    转移指令检测题9
    转移指令笔记(1)
    汇编笔记
    汇编语言学习笔记
    C++中的虚函数
    windows程序设计(四)
    windows程序设计(三)
    windows程序设计(二)
    通过Url网络编程实现下载
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/10682823.html
Copyright © 2020-2023  润新知