题意:给定正整数N和M,统计2和N!之间有多少个整数x满足:x的所有素因子都大
于M(2≤N≤10 7 ,1≤M≤N,N-M≤10 5 )。输出答案除以100000007的余数。例
如,N=100,M=10时答案为43274465。
解题思路:
因为M≤N,所以N!是M!的整数倍。“所有素因子都大于M”等价于和M!互素。另外,根据
最大公约数的性质,对于k>M!,k与M!互素当且仅当k mod M!与M!互素。这样,只需要求
出“不超过M!且与M!互素的正整数个数”,再乘以N!/M!即可。这样,问题的关键就是求出
phi(M!)。因为有多组数据,考虑用递推的方法求出所有的phifac(n)=phi(n!)。由phi函数的公
式:
如果n不是素数,那么n!和(n-1)!的素因子集合完全相同,因此phifac(n)=phifac(n-1)*n;
如果n是素数,那么还会多一项(1-1/n),即(n-1)/n,约分得phifac(n)=phifac(n-1)*(n-1)。

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e7+10;
const long long mod = 100000007;
bool vis[N];
void pre_init(){
    memset(vis, false, sizeof(vis));
    int m = sqrt(N);
    for(int i = 2; i <= m; i++){
        if(!vis[i]){
            for(int j = i * i; j < N; j += i){
                vis[j] = true;
            }
        }
    }
}
long long phifac[N];
int main(){
    pre_init();
    int n, m;
    phifac[1] = phifac[2] = 1; //phifac[1]=1是为了后面不用写特判了
    for(int i = 3; i < N; i++){
        phifac[i] = (long long) phifac[i - 1] * (vis[i] ? i : (i - 1)) % mod;
    }
    while(scanf("%d%d", &n, &m) != EOF)
    {
        if(n == 0 && m == 0) break;
        long long ans = phifac[m];
        for(int i = m + 1; i <= n; i++){
            ans = (long long) ans * i % mod;
        }
        printf("%lld\n", (ans - 1 + mod) % mod);
    }
    return 0;

}