• luogu P4562 [JXOI2018]游戏 组合数学


    LINK:游戏

    当L==1的时候 容易想到 答案和1的位置有关。

    枚举1的位置 那么剩下的方案为(R-1)! 那么总答案为 (R+1)*R/2(R-1)!

    考虑L==2的时候 对于一个排列什么时候会终止 容易发现是L~R中所有的质数 在这个排列中的最后一个位置的影响。

    还是枚举这个质数的位置i 此时方案数为 C(i-1,s-1)s!(n-s)!

    其中s为L~R之中所有的质数个数.

    对于L>2 还是考虑先计算出s的个数 刚才是使用了线性筛 此时考虑 质数不能用了 那么可以考虑每个数是否为必要的数。

    那么我们从前往后推 只需要知道离自己最近的数是谁 看一下上一个是不是就能判断当前了。

    可以发现要除以一下自己的最小质因子。所以线性筛可以解决。

    当然可以直接埃拉筛。统计没被筛到的数字个数即可。复杂度nloglogn

    这里使用前者.

    const int MAXN=10000010,maxn=110,G=3;
    int fac[MAXN],inv[MAXN];
    int v[MAXN],p[MAXN];
    int L,R;
    int cnt,top;
    inline int ksm(int b,int p)
    {
    	int cnt=1;
    	while(p)
    	{
    		if(p&1)cnt=(ll)cnt*b%mod;
    		b=(ll)b*b%mod;p=p>>1;
    	}
    	return cnt;
    }
    inline void prepare()
    {
    	fac[0]=fac[1]=1;
    	rep(2,R,i)
    	{
    		fac[i]=(ll)fac[i-1]*i%mod;
    		if(!v[i])
    		{
    			v[i]=i;
    			p[++top]=i;
    			if(i>=L)++cnt;
    		}
    		rep(1,top,j)
    		{
    			if(p[j]>R/i)break;
    			int ww=i*p[j];
    			v[ww]=p[j];
    			if(i<L&&ww>=L)++cnt;
    			if(v[i]==p[j])break;
    		}
    	}
    }
    inline int C(int a,int b){if(a<b)return 0;return (ll)fac[a]*inv[b]%mod*inv[a-b]%mod;}
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(L);get(R);
    	prepare();
    	if(L==1)put((ll)(1+R)*R/2%mod*fac[R-1]%mod);
    	else
    	{
    		inv[R]=ksm(fac[R],mod-2);
    		fep(R-1,0,i)inv[i]=(ll)inv[i+1]*(i+1)%mod;
    		int n=R-L+1;
    		int ans=0;
    		rep(cnt,n,i)ans=(ans+(ll)C(i-1,cnt-1)*fac[cnt]%mod*fac[n-cnt]%mod*i%mod)%mod;
    		put(ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    oracle 分配表权限给用户的写法
    任务的一种写法:
    解决oracle 32位64位的问题
    设计模式学习
    Nginx 相关介绍
    (2) html 语义化
    (1)HTML5的常用新特性你必须知道
    less初学手记
    如何修改chrome记住密码后自动填充表单的黄色背景 ?
    HTML的水平居中和垂直居中解决方案
  • 原文地址:https://www.cnblogs.com/chdy/p/12813985.html
Copyright © 2020-2023  润新知