[LOJ#6053]简单的函数 题解
最近在搞min_25筛,就写几道筛法题吧
模板题,直接套板子就好了
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); if (ch == '-') ch = getchar(), a = -1; else a = 1; x = ch - '0'; while (ch = getchar(), ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - '0'; return a * x; } const int mod = 1e9 + 7; int inc(int a, int b) { a += b; return a >= mod ? a - mod : a; } int dec(int a, int b) { a -= b; return a < 0 ? a + mod : a; } int fpow(int a, int x) { int ret = 1; for (; x; x >>= 1) { if (x & 1) ret = 1LL * ret * a % mod; a = 1LL * a * a % mod; } return ret; } const int N = 1e5 + 10; int64 n; int p[N], pt, sump[N], sumf[N]; bool fg[N]; int sqrtn; namespace work1 { int f1[N << 1], f2[N << 1]; int id1[N], id2[N], idt; int64 num[N << 1]; int id(int64 x) { if (x <= sqrtn) return id1[x]; else return id2[n / x]; } void solve() { idt = 0; for (int64 i = 1, j; i <= n; i = j + 1) { int64 t = n / i; j = n / t; if (t <= sqrtn) id1[t] = ++idt; else id2[n / t] = ++idt; num[idt] = t; int64 c = t % mod; f1[idt] = (c * (c + 1) / 2 + mod - 1) % mod; f2[idt] = c - 1; } for (int j = 1; j <= pt; ++j) { int64 end = 1LL * p[j] * p[j]; for (int k = 1; num[k] >= end; ++k) { int i = id(num[k] / p[j]); f1[k] = dec(f1[k], 1LL * dec(f1[i], sump[j - 1]) * p[j] % mod); f2[k] = dec(f2[k], 1LL * dec(f2[i], j - 1)); } } } int query(int64 x) { return inc(dec(f1[id(x)], f2[id(x)]), 2 * (x >= 2)); } } namespace work2 { int g[N << 1]; int id1[N], id2[N], idt; int64 num[N << 1]; int id(int64 x) { if (x <= sqrtn) return id1[x]; else return id2[n / x]; } int solve() { for (int64 i = 1, j; i <= n; i = j + 1) { int64 t = n / i; j = n / t; if (t <= sqrtn) id1[t] = ++idt; else id2[n / t] = ++idt; num[idt] = t; g[idt] = work1::query(t); } for (int j = pt; j; --j) { for (int k = 1; num[k] >= 1LL * p[j] * p[j]; ++k) { int i = 1; for (int64 m = p[j]; m * p[j] <= num[k]; ++i, m *= p[j]) { g[k] = inc(g[k], 1LL * dec(g[id(num[k] / m)], sumf[j]) * (p[j] ^ i) % mod); g[k] = inc(g[k], p[j] ^ (i + 1)); } } } return inc(g[id(n)], 1); } } int main() { cin >> n; sqrtn = sqrt(n); for (int i = 2; i <= sqrtn; ++i) { if (!fg[i]) { p[++pt] = i; } for (int j = 1; j <= pt && p[j] * i <= sqrtn; ++j) { fg[p[j] * i] = 1; if (i % p[j] == 0) break; } } for (int i = 1; i <= pt; ++i) sump[i] = inc(sump[i - 1], p[i]), sumf[i] = inc(sumf[i - 1], p[i] ^ 1); work1::solve(); //cerr << work1::query(n) << endl; cout << work2::solve() << endl; }