【校内训练2019-02-21】GT的游戏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/87859969

【思路要点】

  • f i f_i 表示 i i 的最大非平凡因子。
  • 不难发现,游戏结束当且仅当满足 l i r , f i < l l\leq i\leq r,f_i<l i i 都出局。
  • N = r l + 1 N=r-l+1 M M 表示满足 l i r , f i < l l\leq i\leq r,f_i<l i i 的个数,我们可以用动态规划解决该问题,有 A n s N , M = N ! + A n s N , M 1 M + A n s N , M ( N M ) Ans_{N,M}=N!+Ans_{N,M-1}*M+Ans_{N,M}*(N-M)
  • 归纳法可得 A n s N , M = M M + 1 ( N + 1 ) ! Ans_{N,M}=\frac{M}{M+1}*(N+1)!
  • 每隔 α = 1 0 7 \alpha=10^7 个数打一个表,可以计算阶乘,问题在于如何计算 M M
  • l = 1 l=1 ,则 M = 1 M=1 ,下令 l 1 l\ne 1
  • 分开处理质数和合数,考虑计算 2 i r , f i < l 2\leq i\leq r,f_i<l i i 的个数,减去 l 1 l-1
  • 枚举合数的最小质因数,洲阁筛即可。
  • 时间复杂度 O ( α + R 3 4 L o g R ) O(\alpha+\frac{R^{\frac{3}{4}}}{LogR})

【代码】

#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;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/87859969