传送门:点击打开链接
题意:两个士兵正在玩一个游戏,游戏开始的时候,第一个士兵为第二个士兵选一个正整数n。然后第二个士兵要玩尽可能多的轮数。每一轮要选择一个正整数x>1,且n要是x的倍数,然后用n/x去代替n。当n变成1的时候,游戏就结束了,第二个士兵所得的分数就是他玩游戏的轮数。
为了使游戏更加有趣,第一个士兵用 a! / b! 来表示n。k!表示把所有1到k的数字乘起来。
那么第二个士兵所能得到的最大分数是多少呢?
思路:重点是筛选出1~MX内,所有数的质因子的个数之和。如果一个质因子出现了多次,也要计算多次。
其实我们只要在质数筛上面,稍微改一点点就行了,感觉好像只要在质数筛上面稍微修改一点,能解决非常多的类似的问题。
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MX = 5e6 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
LL A[MX];
int cnt[MX], prear;
void prime_init() {
cnt[1] = 0;
for(int i = 2; i < MX; i++) {
if(cnt[i]) continue;
LL s = i;
while(true) {
for(int j = s; j < MX; j += s) {
cnt[j]++;
}
s *= i;
if(s >= MX) break;
}
}
}
void init() {
prime_init();
A[1] = 0;
for(int i = 2; i < MX; i++) {
A[i] = A[i - 1] + cnt[i];
}
}
int main() {
init();
int T; //FIN;
scanf("%d", &T);
while(T--) {
int a, b;
scanf("%d%d", &a, &b);
printf("%I64d\n", A[a] - A[b]);
}
return 0;
}