[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;
} 

 

posted @ 2019-02-28 22:46  AnzheWang  阅读(238)  评论(0编辑  收藏  举报