JZOJ1227 Coprime Problem Solution
Description
For two integers k and m, if the greatest common divisor of k and m is 1, then k and m are relatively prime. Given two positive integers
n and m (m≤n), define f(n,m) as 1~n! Zhong and m! The number of coprime numbers. where n! =1 2 3 .. (n-1)*n.
Task: Given n and m, ask to calculate f(n,m).
Input
This question sets up multiple sets of data.
The first line of the input file has an integer T (1≤T≤100000), indicating that there are T groups of data.
Next there are T lines, each with two integers n and m (2≤n≤100000, 2≤m≤n).
The Output
output file contains T lines, each with an integer representing f(n,m).
Since the answer is too large, you just output f(n,m) mod 131071.
131071 is M17 (Mersen prime, 2^17-1).
Sample Input
1
3 2
Sample Output
3
Idea:
First introduce a theorem: if $gcd(a,b)=1$, then $gcd(a+b,b)=1$.
The proof of this theorem can refer to the "more subtractive method" invented by our ancestors.
We know that the number of numbers that are relatively prime to $m!$ in $1$~$m!$ can be expressed as $\phi(m!)$$(\phi means Euler function)$
So how to express $1$~$ What about the number of numbers that are relatively prime to $m!$ in n!$?
Suppose there is a number $k$ in $1$~$m!$ that is relatively prime to $m!$, according to the previous theorem, $gcd(k+m!,m!)=1$, because $k<m!$ (This is no nonsense), so every $k$ of $gcd(k,m!)1$ can correspond to $m!+1$~$2(m!)$, that is, $m!+1 The number of numbers that are relatively prime to $m!$ in $~$2(m!)$ is $\phi(m!)$, and it can be deduced that: $1$~$n!$ is relatively prime to $m!$ The number of numbers is $$\frac{n!}{m!}\phi(m!)$$
According to the calculation formula of Euler function:
$$\frac{n!}{m!}\phi( m!)=\frac{n!}{m!}{m!}\prod_{p|m!and p is prime}(1-\frac{1}{p})=n!\prod_{p| m! and p is a prime number}(1-\frac{1}{p})$$
Since $n! mod P$ is easy to find, we only need to pay attention to the latter formula, which is $f(m )$:
$$f(m)=\prod_{p|m! and p is prime}(1-\frac{1}{p})$$
we know that $m! = (m-1)! * m $, so $f(m)$ can be pushed from $f(m-1)$.
From $(m-1)!$ to $m!$ only one more m is multiplied, so we only need to consider m. If m is a prime number, then $f(m)=f(m-1)(1-\frac{1}{m})$, otherwise $f(m)=f(m-1)$.
In this way, each $f$ can be preprocessed by the linear sieve method, and the same $n!$ can also be preprocessed, and the answer is $n! f(m)$
Code:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
typedef long long ll;
const int N = 1e5 + 3;
const ll P = 131071;
int t, tot = 0, check[N], prime[N / 10];
ll n, m, jc[N], phi[N];
ll pow(ll x, ll p) //快速幂求逆元
{
ll ret = 1;
while (p)
{
if (p & 1) ret = ret * x % P;
x = x * x % P;
p >>= 1;
}
return ret;
}
int main()
{
freopen("coprime.in", "r", stdin);
freopen("coprime.out", "w", stdout);
jc[1] = 1; for (int i = 2; i <= N - 3; i++) jc[i] = jc[i - 1] * i % P; //预处理n!
phi[1] = 1;
for (int i = 2; i <= N - 3; i++) //用线筛计算f
{
phi[i] = phi[i - 1];
if (!check[i]) phi[i] = phi[i] * (i - 1) % P * pow(i, P - 2) % P, prime[++tot] = i; //i为质数,递推
for (int j = 1; j <= tot; j++)
{
if (i * prime[j] > N - 3) break;
check[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
scanf("%d", &t);
while (t--)
{
scanf("%lld%lld", &n, &m);
printf("%lld\n", phi[m] * jc[n] % P); //答案就是n!*f(m)
}
fclose(stdin);
fclose(stdout);
return 0;
}