【题解】BZOJ 2721 [Violet 5]樱花

传送门

Description D e s c r i p t i o n

求出有多少对 (x,y) ( x , y ) 满足

1x+1y=1n! 1 x + 1 y = 1 n !

Solution S o l u t i o n

首先是对公式进行变形

1x+1y=1n!xn!+yn!=xyxyxn!yn!+(n!)2=(n!)2(xn!)(yn!)=(n!)2 1 x + 1 y = 1 n ! x ⋅ n ! + y ⋅ n ! = x y x y − x ⋅ n ! − y ⋅ n ! + ( n ! ) 2 = ( n ! ) 2 ( x − n ! ) ⋅ ( y − n ! ) = ( n ! ) 2

接下来我们令 p=xn! p = x − n ! q=yn! q = y − n ! 。就变成了 pq=(n!)2 p ⋅ q = ( n ! ) 2

这下问题就转化成求 (n!)2 ( n ! ) 2 有多少个约数。

我们写出 n! n ! 的唯一分解式:

n!=pα11pα22pαkk n ! = p 1 α 1 ⋅ p 2 α 2 ⋯ p k α k


(n!)2=p2α11p2α22p2αkk ( n ! ) 2 = p 1 2 α 1 ⋅ p 2 2 α 2 ⋯ p k 2 α k

那么 (n!)2 ( n ! ) 2 的约数个数等于

(2α1+1)(2α2+1)(2αk+1) ( 2 α 1 + 1 ) ( 2 α 2 + 1 ) ⋯ ( 2 α k + 1 )

直接计算即可。

Code C o d e

#include
#include
#include
#include
#define N 10000000
#define P 1000000007
int prime[N], number[N], f[N];
int main() {
    int n; int cnt = 0;
    scanf("%d", &n);
    for (int i = 2; i <= n; i++) {    // 线性筛
        if (f[i] == 0) {
            cnt++;
            prime[cnt] = i; 
            f[i] = cnt;
        }
        for (int j = 1; j <= cnt; j++){
            if (prime[j] * i > n) break;
            f[prime[j] * i] = j;
            if (i % prime[j] == 0) break;
        }
    }   
    for (int i = 2; i <= n; i++) {
        int x = i;
        while (x != 1) {        // 分解 i
            int j = prime[f[x]];
            while (x % j == 0) {
                number[f[x]]++;
                x /= j;
            }
        }
    }
    long long sum = 1;
    for (int i = 1; i <= cnt; i++)   // 计算结果
        if (number[i] != 0) 
            (sum *= (2ll * number[i] + 1ll)) %= P;
    printf("%lld\n", sum);
    return 0;
}

你可能感兴趣的:(BZOJ,数论,线性筛)