zoukankan      html  css  js  c++  java
  • [JXOI2018]游戏

    洛咕

    题意:给一个区间[l,r],每次选一个数.把它和它的倍数去掉,耗时为[l,r]的所有数都被消掉的次数,求所有不同选择方案的总耗时.

    分析:对于区间[3,9]来说,3,4,5,7这四个数字必须要主动去消,我们假设称这样的数字为"关键数",则对于任意一种选择方案,最后一次(主动)消去的数字一定是一个"关键数".

    假设区间[l,r]内有sum个"关键数"(sum可以直接埃氏筛暴力得出).则对于任意一种选择方案,最少需要消sum次,最多需要消n(n=r-l+1)次.

    假设有一类选择方案是要消i次,则这一类选择方案总耗时为(i*(sum*(i-1)!*C_{n-sum}^{n-i}*(n-i)!)),解释式子:

    最后一次(第i次)消去的一定是"关键数",且是(sum)中任意一个,前(i-1)个数可以任意排列,即有((i-1)!)中排列方案,后面的(n-i)个数一定全都是"非关键数",一共有(n-sum)个"非关键数",故有(C_{n-sum}^{n-i})种选择方案,后面(n-i)个数也可以任意排列,即有((n-i)!)种选择方案.故消i次一共有(sum*(i-1)!*C_{n-sum}^{n-i}*(n-i)!)种选择方案,消i次的总耗时为(i*(sum*(i-1)!*C_{n-sum}^{n-i}*(n-i)!))

    所有最后的答案就是(ans=sum_{i=sum}^{i=n}i*(sum*(i-1)!*C_{n-sum}^{n-i}*(n-i)!))

    我下面的代码也是为了卡常 费尽心思了的...

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define mod 1000000007
    #define N 10000007
    #define rg register
    using namespace std;
    inline int read(){
        rg int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    inline void write(int x){
        if(x<0)putchar('-'),x=-x;
        if(x>9)write(x/10);
        putchar(x%10+'0');
    }
    int sum,ans,visit[N],jc[N],ny[N];
    inline int ksm(int a,int b){
        rg int cnt=1;
        while(b){
    		if(b&1)cnt=1ll*cnt*a%mod;
    		a=1ll*a*a%mod;
    		b>>=1;
        }
        return cnt%mod;
    }
    inline int C(int n,int m){return n<m?0:1ll*jc[n]*ny[m]%mod*ny[n-m]%mod;}
    inline void get_jc(int n){
        jc[0]=1;
        for(rg int i=1;i<=n;++i)jc[i]=1ll*jc[i-1]*i%mod;
        ny[n]=ksm(jc[n],mod-2);
        for(rg int i=n-1;i>=0;--i)ny[i]=1ll*ny[i+1]*(i+1)%mod;
        return;
    }
    inline void get_num(int l,int r){
        for(rg int i=l;i<=r;++i){
    		if(visit[i])continue;
    		sum++;
    		for(rg int j=i;j<=r;j+=i)visit[j]=1;
        }
        return;
    }
    int main(){
        rg int l=read(),r=read(),n=r-l+1;
        get_num(l,r),get_jc(r);
        for(rg int i=sum;i<=n;++i){
    		rg int res=1ll*i*sum%mod;
    		res=1ll*res*jc[i-1]%mod;
    		res=1ll*res*jc[n-i]%mod;
    		res=1ll*res*C(n-sum,n-i)%mod;
    		ans=(ans+res)%mod;
        }
        write(ans);
        return 0;
    }
    
    
  • 相关阅读:
    【TypeScript】TypeScript中的数据类型
    正则表达式
    约束和异常处理
    面向对象-成员
    初识面向对象
    内置函数二
    生成器和生成器表达式
    函数名的运用
    函数
    文件操作
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10628306.html
Copyright © 2011-2022 走看看