P4917 天守阁的地板

P4917 天守阁的地板

写得我头疼。

容易发现,任意两个数要拼成一个正方形,最小边长是 \(\operatorname{lcm}(i,j)\)

那么需要用的数量就是 \(\dfrac{\operatorname{lcm}(i,j)^2}{i \cdot j}\)

所以我们要求的就是 \(\displaystyle \prod_{i=1}^N \prod_{j=1}^N \dfrac{\operatorname{lcm}(i, j)^2}{i \cdot j}\)

转化一下就是 \(\displaystyle \prod_{i=1}^N \prod_{j=1}^N \dfrac{i \cdot j}{\gcd(i,j)^2}\)

接下来就是 \(\displaystyle \dfrac{\large (n!)^{2n}}{\displaystyle \prod_{i=1}^N \prod_{j=1}^N \gcd(i, j)^2}\)

然后我们令 \(d = gcd(i, j)\)

那么 \(\displaystyle \dfrac{\large (n!)^{2n}}{\displaystyle \prod_{d=1}^N d^{2 \cdot 2 \sum_{i=1}^{\lfloor \frac{N}{d} \rfloor } \sum_{j=1}^{\lfloor \frac{N}{d} \rfloor }[gcd(i,j)=1]}}\)

然后经过莫比乌斯反演(懒得写了)

然后得到 \(\displaystyle \dfrac{\large (n!)^{2n}}{\displaystyle \prod_{d=1}^N d^{2 \cdot 2 \sum_{k=1}^{\lfloor \frac{N}{d} \rfloor} \mu(k) \cdot (\lfloor \frac{N}{kd} \rfloor )^2}}\)

感觉是可以做了,但是我写挂了,然后换了个方法。。。

你考虑这就是求了一个数表内互质的数

那么可以换成

\[\huge \displaystyle \dfrac{ (n!)^{2n}}{\displaystyle \prod_{d=1}^N d^{2 \cdot \Big(2 \cdot \sum_{i=1}^{\lfloor \frac{N}{d} \rfloor} \varphi\big(i\big)\Big) - 1}} \]

注:\(-1\) 是因为 \(\varphi(1)\) 被算了两遍。

下面就是各位的代码能力了。。。


下面是我的代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

typedef long long ll;
const ll MAXN = 1e6+10, MOD = 19260817;

ll N, T, fac[MAXN], phi[MAXN], prime[MAXN], cnt, vis[MAXN], inv[MAXN];

ll ks(ll, ll);
ll f(ll);

int main() {
    scanf("%lld", &T);
    fac[0] = fac[1] = inv[0] = inv[1] = 1;
    for (ll i = 2; i <= MAXN - 10; i++)
        fac[i] = fac[i-1] * i % MOD, inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
    for (ll i = 2; i <= MAXN - 10; i++)	
    	inv[i] = inv[i-1] * inv[i] % MOD;
    phi[1] = 1;
    for (ll i = 2; i <= MAXN - 10; i++) {
        if (!vis[i]) prime[++cnt] = i, phi[i] = i-1;
        for (ll j = 1; j <= cnt && prime[j] * i <= MAXN - 10; j++) {
            vis[i * prime[j]] = 1;
            if (i % prime[j]) {
                phi[i * prime[j]] = phi[i] * phi[prime[j]];
            } else {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
        }
    }
    for (ll i = 1; i <= MAXN - 10; i++)
    	phi[i] = (phi[i] + phi[i-1]) % (MOD - 1); // phi出现在指数,那么 mod (MOD-1)
    while (T--) {
        scanf("%lld", &N);
        ll up = ks(fac[N], (2 * N) % MOD) % MOD;
        ll down = 1;
        for (ll l = 1, r = 0; l <= N; l = r + 1) {
            r = (N / (N / l));
            ll gx = phi[N / l] * 2 - 1;
            down = down * ks(fac[r] * inv[l-1] % MOD, gx) % MOD;
        }
        down = down * down % MOD;
        printf("%lld\n", up * ks(down, MOD-2) % MOD);
    }
    return 0;
}

ll ks(ll n, ll tim) {
    ll ret = 1;
    while (tim) {
        if (tim & 1) ret = ret * n % MOD;
        n = n * n % MOD;
        tim >>= 1;
    }
    return ret % MOD;
}

posted @ 2020-10-22 18:02  Gensokyo_Alice  阅读(49)  评论(0编辑  收藏  举报