P5221 Product
这题好像可以用莫反做,但数论分块似乎会被卡
i=1∏nj=1∏ngcd(i,j)lcm(i,j)=i=1∏nj=1∏ngcd(i,j)2ij=i=1∏nj=1∏nij×i=1∏nj=1∏ngcd(i,j)−2
首先看 i=1∏nj=1∏nij
=i=1∏ninj=1∏nj=i=1∏ninn!=(n!)n×(n!)n=(n!)2n
接着尝试化简一下后面那一坨
i=1∏nj=1∏ngcd(i,j)=d=1∏ndi=1∑nj=1∑n[gcd(i,j)=d]=d=1∏ndi=1∑dnj=1∑dn[gcd(i,j)=1]
仔细观察一下指数,发现可以用莫反加数论分块,但时间复杂度就是 O(nn), 有点勉强,所以可以考虑欧拉函数 i=1∑nj=1∑i[gcd(i,j)=1]=i=1∑nϕ(i)
令 sum(n)=i=1∑nϕ(i) 那么上述式子的指数 =2×sum(⌊dn⌋)−1
⇒ans=(n!)2n×d=1∏nd2×sum(⌊dn⌋)−1
因为此题卡空间,数组不能开long long,所以需要用到欧拉定理 ac≡ac mod ϕ(m)(mod m), 这样就不需要开long long了
代码
#include<iostream> #include<cstdio> #define MOD (104857601) using namespace std; typedef long long ll; const int N = 1e6 + 5;
bool st[N]; int phi[N], prime[N], tot;
void init() { phi[1] = 1; for (int i = 2; i < N; i++) { if (!st[i]) prime[++tot] = i, phi[i] = i - 1; for (int j = 1; i * prime[j] < N; j++) { st[i * prime[j]] = true; if (i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } for (int i = 1; i < N; i++) phi[i] = (phi[i] + phi[i - 1]) % (MOD - 1); }
int qmi(int a, ll b) { int res = 1; while (b) { if (b & 1) res = (ll)res * a % MOD; a = (ll)a * a % MOD; b >>= 1; } return res; }
int main() { init(); int n; scanf("%d", &n); int ans = 1; for (int i = 1; i <= n; i++) ans = (ll)ans * i % MOD; ans = qmi(ans, 2 * n); int temp = 1; for (int i = 2; i <= n; i++) temp = (ll)temp * qmi(i, 2 * phi[n / i] - 1) % MOD; temp = (ll)temp * temp % MOD; temp = qmi(temp, MOD - 2); printf("%d", (ll)temp * ans % MOD); return 0; }
|