Description:
定义函数
\[ f _n (k) = \sum _{l _1 = 1} ^n \sum _{l _2 = 1} ^n \cdots \sum _{l _k = 1} ^n \gcd(l _1, l _2, \cdots, l _k) ^2 \]
现给定 \(n, k\),需要求出 \(\sum _{i = 2} ^k f _n (i)\),答案对 \(10 ^9 + 7\) 取模。
\(T\) 组数据。
\[ 1 \le T \le 10, 1 \le n \le 10 ^9, 2 \le k \le 10 ^{10 ^5} \]
Solution:
\[ \begin{aligned} f_n(k) &= \sum_{d=1}^nd^2\sum_{x=1}^\frac{n}{d}\mu(x)\lfloor\frac{n}{dx}\rfloor ^k\\ &=\sum_{T=1}^n\lfloor\frac{n}{T}\rfloor^k\sum_{d|T}\mu(d)\left(\frac{T}{d}\right)^2 \end{aligned} \]
答案为:
\[ \begin{aligned} &\sum_{i=2}^k\sum_{T=1}^n\lfloor\frac{n}{T}\rfloor^i\sum_{d|T}\mu(d)\left(\frac{T}{d}\right)^2\\ =&\sum_{T=1}^n\left(\sum_{i=2}^k\lfloor\frac{n}{T}\rfloor^i\right)\left(\sum_{d|T}\mu(d)\left(\frac{T}{d}\right)^2\right) \end{aligned} \]
前面整除分块+等比数列求和,后面杜教筛。
Code:
#include <iostream> #include <vector> #include <map> #include <cstdio> #include <cstring> #include <algorithm> #include <fstream> typedef long long LL; typedef unsigned long long uLL; #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define MP(x, y) std::make_pair(x, y) #define DEBUG(...) fprintf(stderr, __VA_ARGS__) #define GO cerr << "GO" << endl; using namespace std; inline void proc_status() { ifstream t("/proc/self/status"); cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl; } template<class T> inline T read() { register T x(0); register char c; register int f(1); while (!isdigit(c = getchar())) if (c == '-') f = -1; while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar())); return x * f; } template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; } template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; } const int maxN = 5e6; const int mod = 1e9 + 7; LL qpow(LL a, LL b) { LL ans = 1; while (b) { if (b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans; } LL k, kk; LL calc(int x) { if (x == 1) return (kk - 1 + mod) % mod; else return (LL)x * (qpow(x, k) - x + mod) % mod * qpow(x - 1, mod - 2) % mod; } void Read() { k = kk = 0; register char c; while (!isdigit(c = getchar())); while (k = (k * 10 + (c xor 48)) % (mod - 1), kk = (kk * 10 + (c xor 48)) % mod, isdigit(c = getchar())); } vector<int> prime; bool vis[maxN + 2]; int f[maxN + 2], inv6; map<int, int> F; void Init() { f[1] = 1; for (register int i = 2; i <= maxN; ++i) { if (!vis[i]) { f[i] = ((LL)i * i - 1) % mod; prime.push_back(i); } for (register int j = 0; j < SZ(prime) && prime[j] * i <= maxN; ++j) { int t = prime[j] * i; vis[t] = 1; if (i % prime[j] == 0) { f[t] = (LL)f[i] * prime[j] % mod * prime[j] % mod; break; } else f[t] = (LL)f[i] * f[prime[j]] % mod; } } for (register int i = 2; i <= maxN; ++i) f[i] += f[i - 1], f[i] %= mod; } int Sum(int n) { if (n <= maxN) return f[n]; if (F.count(n)) return F[n]; LL ans = (LL)n * (n + 1) % mod * (2ll * n + 1) % mod * inv6 % mod; for (int l = 2, r; l <= n; l = r + 1) { r = n / (n / l); ans += mod - (LL)Sum(n / l) * (r - l + 1) % mod; ans %= mod; } return F[n] = ans % mod; } int main() { #ifndef ONLINE_JUDGE freopen("xhc.in", "r", stdin); freopen("xhc.out", "w", stdout); #endif int T = read<int>(); inv6 = qpow(6, mod - 2); Init(); while (T--) { LL ans(0); int n; n = read<int>(), Read(); for (int l = 1, r; l <= n; l = r + 1) { r = n / (n / l); ans += calc(n / r) * (Sum(r) - Sum(l - 1) + mod) % mod; ans %= mod; } printf("%d\n", (int) ans); } return 0; }
来源:博客园
作者:茶Tea
链接:https://www.cnblogs.com/cnyali-Tea/p/11510521.html