(2017多校訓練第二場)HDU
阿新 • • 發佈:2019-01-07
第一次接觸莫比烏斯這麼高階的東西,心裡很是激動。
莫比烏斯是照著ACdreamer大神的部落格學習的:點選開啟連結
本來想寫一篇詳細的部落格紀念一下第一次寫莫比烏斯,但是鑑於時間太晚(從23:00一直TLE到01:28),這裡就給大家推薦一篇講得很好的部落格:點選開啟連結
程式碼如下:
#include <bits/stdc++.h> using namespace std; typedef long long int LL; const int MOD = 1e9+7; const int MAX_N = 1e5+5; const int INF = 0x3f3f3f3f; int prime[MAX_N], cnt; int vis[MAX_N]; int u[MAX_N]; // 莫比烏斯函式 // 快速線性篩法求莫比烏斯函式 void Mobius() { memset(vis, 0, sizeof(vis)); u[1] = 1; cnt = 0; for (LL i = 2; i < MAX_N; i++) { if (!vis[i]) { prime[cnt++] = i; u[i] = -1; } for (LL j = 0; j < cnt && i * prime[j] < MAX_N; j++) { vis[i * prime[j]] = 1; if (i % prime[j]) u[i * prime[j]] = -u[i]; else { u[i * prime[j]] = 0; break; } } } } LL mod_pow(LL a, LL n, LL mod) { LL res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; } int main() { //freopen("test.txt", "r", stdin); //freopen("out.txt", "w", stdout); cin.sync_with_stdio(false); Mobius(); int T, Case = 1; int A[MAX_N], n; cin >> T; while (T--) { cin >> n; int Max = -1, Min = INF; int pre[2 * MAX_N] = {0}; for (int i = 1; i <= n; i++) { cin >> A[i]; Max = max(Max, A[i]); Min = min(Min, A[i]); pre[A[i]]++; } for (int i = 1; i < 2 * MAX_N; i++) pre[i] += pre[i - 1]; LL ans = 0; for (int i = 2; i <= Min; i++) { LL tmp = 1; for (int j = 1; j * i <= Max; j++) tmp = (tmp * mod_pow(j, pre[i * (j + 1) - 1] - pre[i * j - 1], MOD)) % MOD; ans = (ans - u[i] * tmp + MOD) % MOD; } cout << "Case #"<< Case++ << ": " << ans << endl; } return 0; }