1. 程式人生 > 其它 >AcWing 1294. 櫻花

AcWing 1294. 櫻花

題目傳送門

一、解題思路

做了這題,感覺這類題目的大多數分析過程都是這樣的:

  • 求有多少對整數對\((x,y)\)滿足一條方程,則方程一定存在解,將\(y\)轉換為關於\(x\)的表示式,再根據\(y\)的約數條件,求出\((x,y)\)的匹配數,即一個\(x\)對應一個\(y\)

1、確定\(x,y\)範圍

\[\frac{1}{x}+\frac{1}{y}=\frac{1}{n!} \]

\(x,y∈Z^+\)
\(x>n!\) \(y>n!\) 小學數學知識~

2、推表示式

轉換為y的表示式

\[\frac{x+y}{xy}=\frac{1}{n!} \]

變形

\[xn!+yn!=xy \]

繼續變形

\[xn!=y(x-n!) \] \[y=\frac{xn!}{x-n!} \]

經典的變形技巧:

\[y=\frac{(x-n!+n!)n!}{x-n!} \] \[y=\frac{(x-n!)n!+n!^2}{x-n!} \] \[y=n! + \frac{n!^2}{x-n!} \]

因為上面已經證明了\(x-n!>0\)的,所以要想\(y\)有正整數解,則必然需要

\[(x-n!)|n!^2 \]

換句話說,就是\(n!^2\)有多少個約數,就有相應的正整數\(x\),也就有一個對應的\(y\)
如果我們能夠求得\(n!^2\)

的約數個數,也就是\({x,y}\)的匹配對數。

3、階乘分解質因數

參考 \(Acwing197\). 階乘分解 的方法

  • 先篩出\(n\)以內的質數
  • 計算每個質數因子出現的次數
 for (int i = 0; i < cnt; i++) {
        int p = primes[i];
        int s = 0;
        for (int j = n; j; j /= p) s += j / p;
        printf("%d %d\n", p, s);
    }

4、約數個數

\(n!^2\)一共有多少個約數
假設$$n!=P_1^{c_1} \times P_2^{c_2}\times ...\times P_k^{c_k}$$
則$$n!2=P_1

{2c_1}\times P_2^{2c_2}\times ...\times P_k^{2c_k}$$

根據約數個數定理
知道約數的個數是\((2c_1+1)\times (2c_2+1)\times …\times (2c_k+1)\)

5、時間複雜度 \(O(n)\)

二、實現程式碼

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;

//尤拉篩
const int N = 1e6 + 10;
int primes[N], cnt; // primes[]儲存所有素數
bool st[N];         // st[x]儲存x是否被篩掉
void get_primes(int n) {
    memset(st, 0, sizeof st);
    cnt = 0;
    for (int i = 2; i <= n; i++) {
        if (!st[i]) primes[cnt++] = i;
        for (int j = 0; primes[j] * i <= n; j++) {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
int main() {
    int n;
    cin >> n;
    //步驟1:篩質數
    get_primes(n);
    //步驟2:階乘質因子分解
    int res = 1;
    for (int i = 0; i < cnt; i++) {
        int p = primes[i];
        int s = 0;
        for (int j = n; j; j /= p) s += j / p;
        //步驟3:約數個數公式
        res = (LL)res * (2 * s + 1) % mod;
    }
    cout << res << endl;
    return 0;
}

三、知識點總結

  • 數學公式推導
    轉化為一個自變數,一個因變數的形式,最終描述:有一個\(x\),就能確定一個\(y\),需要滿足xxx條件(一般是誰能整除誰之類,轉化為求約數個數)

  • 唯一分解定理

  • 階乘的質因子分解
    經典作法,除了背下來,多看幾遍,還有啥更好的辦法~

  • 約數和公式