JZOJ1227 Coprime Problem Solution

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324821095&siteId=291194637