版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/87859969
【思路要点】
- 记 表示 的最大非平凡因子。
- 不难发现,游戏结束当且仅当满足 的 都出局。
- 记 , 表示满足 的 的个数,我们可以用动态规划解决该问题,有 。
- 归纳法可得 。
- 每隔 个数打一个表,可以计算阶乘,问题在于如何计算 。
- 若 ,则 ,下令 。
- 分开处理质数和合数,考虑计算 的 的个数,减去 。
- 枚举合数的最小质因数,洲阁筛即可。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 5; const int P = 1e9 + 7; const int alpha = 1e7; const int table[101] = {1, 682498929, 491101308, 76479948, 723816384, 67347853, 27368307, 625544428, 199888908, 888050723, 927880474, 281863274, 661224977, 623534362, 970055531, 261384175, 195888993, 66404266, 547665832, 109838563, 933245637, 724691727, 368925948, 268838846, 136026497, 112390913, 135498044, 217544623, 419363534, 500780548, 668123525, 128487469, 30977140, 522049725, 309058615, 386027524, 189239124, 148528617, 940567523, 917084264, 429277690, 996164327, 358655417, 568392357, 780072518, 462639908, 275105629, 909210595, 99199382, 703397904, 733333339, 97830135, 608823837, 256141983, 141827977, 696628828, 637939935, 811575797, 848924691, 131772368, 724464507, 272814771, 326159309, 456152084, 903466878, 92255682, 769795511, 373745190, 606241871, 825871994, 957939114, 435887178, 852304035, 663307737, 375297772, 217598709, 624148346, 671734977, 624500515, 748510389, 203191898, 423951674, 629786193, 672850561, 814362881, 823845496, 116667533, 256473217, 627655552, 245795606, 586445753, 172114298, 193781724, 778983779, 83868974, 315103615, 965785236, 492741665, 377329025, 847549272, 698611116}; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int tot, limit, prime[MAXN], f[MAXN]; int m1, val1[MAXN], cnt1[MAXN], home1[MAXN], home2[MAXN]; int m2, val2[MAXN], cnt2[MAXN], home3[MAXN], home4[MAXN]; void sieve(int n) { for (int i = 2; i <= n; i++) { if (f[i] == 0) prime[++tot] = f[i] = i; for (int j = 1; j <= tot && prime[j] <= f[i]; j++) { int tmp = prime[j] * i; if (tmp > n) break; f[tmp] = prime[j]; } } } int getcnt(int l, int r) { if (l == 1) return 1; int ans = 0, limit = sqrt(r); l--, sieve(limit); for (int i = 1, nxt; i <= r; i = nxt + 1) { int tmp = r / i; val1[++m1] = tmp; if (tmp <= limit) home1[tmp] = m1; else home2[r / tmp] = m1; nxt = r / val1[m1]; cnt1[m1] = tmp - 1; } for (int i = 1, nxt; i <= l; i = nxt + 1) { int tmp = l / i; val2[++m2] = tmp; if (tmp <= limit) home3[tmp] = m2; else home4[r / tmp] = m2; nxt = l / val2[m2]; cnt2[m2] = tmp - 1; } for (int i = 1; i <= tot; i++) { if (1ll * prime[i] * l <= r) ans += l >= prime[i] ? cnt2[1] - (i - 1) : 0; else { int tmp = r / prime[i], pos = 0; if (tmp <= limit) pos = home1[tmp]; else pos = home2[r / tmp]; ans += cnt1[pos] - (i - 1); } for (int j = 1; prime[i] * prime[i] <= val1[j]; j++) { int tmp = val1[j] / prime[i], pos = 0; if (tmp <= limit) pos = home1[tmp]; else pos = home2[r / tmp]; cnt1[j] -= cnt1[pos] - (i - 1); } for (int j = 1; prime[i] * prime[i] <= val2[j]; j++) { int tmp = val2[j] / prime[i], pos = 0; if (tmp <= limit) pos = home3[tmp]; else pos = home4[r / tmp]; cnt2[j] -= cnt2[pos] - (i - 1); } } ans += cnt1[1] - l + 1; return ans; } int power(int x, int y) { if (y == 0) return 1; int tmp = power(x, y / 2); if (y % 2 == 0) return 1ll * tmp * tmp % P; else return 1ll * tmp * tmp % P * x % P; } int fac(int x) { int ans = table[x / alpha]; for (int i = x / alpha * alpha + 1; i <= x; i++) ans = 1ll * ans * i % P; return ans; } int main() { freopen("number.in", "r", stdin); freopen("number.out", "w", stdout); int l, r; read(l), read(r); int cnt = getcnt(l, r); printf("%lld\n", 1ll * cnt * power(cnt + 1, P - 2) % P * fac(r - l + 2) % P); return 0; }