游戏
题目链接
题目链接
题解
我们发现,对于一系列具有倍数关系数字2,4,6,8,检查时间其实是由他们种最小的数所决定的,以样例为例,将2,4分为一类,3分为一类,最后的检查时间是由2和3的位置所决定,所以可以枚举所有可能的时间,接下来就是排列组合的事情了,具体见代码
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 | #include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e7 + 5;
int fac[N], infac[N];
int pre[N];
bool vis[N];
int sz[N];
int qpow(int a, int n, int mod) {
int res = 1;
while(n) {
if(n & 1) res = res * a % mod;
a = a * a % mod;
n >>= 1;
}
return res;
}
void init(int n) { //预处理阶乘和逆元
fac[0] = 1;
infac[0] = 1;
for(int i = 1; i <= n; i ++ ) fac[i] = fac[i - 1] * i % mod;
infac[n] = qpow(fac[n], mod - 2, mod);
for(int i = n - 1; i >= 1; i -- ) {
infac[i] = infac[i + 1] * (i + 1) % mod;
}
//for(int i = 1; i <= 10; i ++ ) cout << fac[i] << " ";
//cout << endl;
//for(int j = 1; j <= 10; j ++ ) cout << infac[j] << " ";
//cout << endl;
}
inline int find(int x) {
return x == pre[x] ? x : pre[x] = find(pre[x]);
}
int C(int a, int b) {
return fac[a] % mod * infac[a - b] % mod * infac[b] % mod;
}
signed main() {
int l, r;
cin >> l >> r;
init(r + 1);
int n = r - l + 1;
int x = 0; // x为最小的数的个数
for(int i = l; i <= r; i ++ ) {
if(vis[i]) continue;
x ++ ;
for(int j = 2; j * i <= r; j ++ ) {
if(vis[i * j]) continue;
vis[i * j] = true;
//cout << i << " " << j << endl;
}
}
//for(int i = l; i <= r; i ++ ) cout << pre[i] << " ";
int res = 0;
//cout << C(5, 3) << endl;
//cout << x << endl;
for(int i = x; i <= n; i ++ ) { // 枚举可能的时间
res += x * C(n - x, i - x) % mod * fac[i - 1] % mod * fac[n - i] % mod * i % mod;
res %= mod;
}
// 对于时间是i的情况,说明x个数必须在前i个位置且有一个处于第i个位置,于是固定第i个位置,前面和后面全排列即可
cout << res << endl;
return 0;
}
|