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

  • 相关阅读:
    oracle 大文本由clob来存
    merge into 语法缺陷
    基本元素的增加 jquery
    报表 jquery
    购物车的高级实现 逻辑结构清晰
    购物车的实现 js
    定时器的制作与清除
    div的大小设置
    二级菜单联动(自定义框架)
    编写数组删除模板
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15500627.html
Copyright © 2011-2022 走看看