P4562 [JXOI2018]游戏
给定一个区间[L,R],每次可以去除区间一个数字及其它的倍数,求把整个区间消去的步数的所有情况的和
我们可以定义整个区间伪素数为这个区间没有它的倍数的数,那么一个消去顺序的步数就是最后面的伪素数。那么我们可以枚举这个最右边的伪素数的质数的位置为i,依次算出每个位置的贡献,方案数
设伪素数的个数为sum,区间长度为n
那么总答案为
求伪素数的方法可以用埃氏筛
时间复杂度\(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, '\n');
return 0;
}