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

    给定一个区间[L,R],每次可以去除区间一个数字及其它的倍数,求把整个区间消去的步数的所有情况的和

    我们可以定义整个区间伪素数为这个区间没有它的倍数的数,那么一个消去顺序的步数就是最后面的伪素数。那么我们可以枚举这个最右边的伪素数的质数的位置为i,依次算出每个位置的贡献,方案数
    设伪素数的个数为sum,区间长度为n
    那么总答案为

    [sum_{sum}^{n} i(步数)*sum(最右边伪素数的种类)* \ inom{n-sum}{n-i}(最右边伪素数的右边非伪素数的方案) \ * (n-i)(右边数字的全排列)! *(i-1) ! ]

    求伪素数的方法可以用埃氏筛
    时间复杂度(O(n log log n))

    lxl inv_fac[N], fac[N];
    lxl len, sum, ans, temp;
    bool v[N];
    inline void init() {
    	fac[0] = 1;
    	rep(i, 1, len) {
    		fac[i] = fac[i - 1] * i % mod;
    	}
    
    	inv_fac[len] = Quick_Pow(fac[len], mod - 2);
    	drp(i, len - 1, 0) {
    		inv_fac[i] = inv_fac[i + 1] * (i + 1) % mod;
    	}
    
    
    	rep(i, L, R) {
    		if(v[i]) continue;
    		++sum;
    		for(int j(i << 1); j <= R; j += i) {
    			v[j] = 1;
    		}
    	}
    }
    
    inline lxl C(int n, int m) {
    	if(n < m) {
    		return 0;
    	}
    	return fac[n] * inv_fac[m] % mod * inv_fac[n - m] % mod;
    }
    
    int main() {
    	read(L);
    	read(R);
    	len = R - L + 1;
    
    	init();
    
    	rep(i, sum, len) {
    		
    		temp = 1ll * i * sum % mod;
    		temp = temp * C(len - sum, len - i) % mod;
    		temp = temp * fac[len - i] % mod * fac[i - 1] % mod;
    		ans = (ans + temp) % mod;
    	}
    	out(ans, '
    ');
    	return 0;
    
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15500627.html

  • 相关阅读:
    subsonic资源聚合
    一些经典的框架
    小毛看传统图书行业
    商界传媒20092010 从容就业,激情创业(企业家走进北在)活动记
    Beijing Perl Workshop 2009
    智力更生小毛笔记&心得
    使用world 2007 或是windows live writer写blog的设置
    php技术准备
    我需要知道的技术常识
    重新分配ip
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15500627.html
Copyright © 2011-2022 走看看