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

  • 相关阅读:
    数论数论函数基础知识
    KMP入门和简单运用
    高斯消元入门
    FFT和NTT
    AC自动机入门和简单应用
    后缀自动机入门
    线段树优化建图的速成
    爱情九十七课,降低期待
    爱情九十二课,说出你的弱
    爱情八十六课,等得不是爱情
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15500627.html
Copyright © 2011-2022 走看看