MIN25筛的瞎扯:
在复杂度
下解决一些积性函数的和
做一些规定:
表示第
个质数,规定第零个质数为1;
都是指质数
目的:求
要求:
是一个积性函数(即,
互质时,
)
可以快速求
是一个是一个关于
的项数较少的多项式,或可以快速求值
令
因为只要分别求出
的前
项和,再与系数相乘,再把各项加起来就行
所以令
=
我们把问题简化为两部分来
第一部分
求解
因为一个合数
的最小质因子不大于
所以
,这里的|p|表示不大于
的最大质数。
显然
现在来考虑怎么
。
从
会少掉一些合数的最小质因子是
的,所以要减掉。
若
则不存在这样的合数
此时有
那么
时
所以
包含了小于
的质数和大于
且其最小质因子大于等于
的
值
所以
包含了最小质因子大于等于
的
值。
所以有
第二部分
求解
则答案为
易知
,
为大于
的质数
第二部分其实道理跟第一部分一样的,自己推导一下就行。
结果:
可以看到我们需要的
点有
一共
个点,所以需要一些分块
例题:简单的函数
#include<bits/stdc++.h>
#define ll long long
#define ull unsiged ll
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, r, l) for (int i = r; i >= l; i--)
#define boots ios::sync_with_stdio(0); cin.tie(0)
#define endl '\n'
#define mod 1000000007
#define inf 0x3f3f3f3f
#define lnf LLONG_MAX
#define si(n) scanf("%d", &n)
#define sl(n) scanf("%lld", &n)
#define pf(n) printf("%lld\n", n)
#define sz size
using namespace std;
//const db pi = 3.1415926535898;
const int N = 2e5 + 10;
const int INV2 = 500000004;
int top;
unordered_map<ll, ll> mp;
int pri[N], ji[N];
ll g[N], h[N], pris[N];
ll w[N];
//pri[i]表示第几个质数,pris[i]表示前i个质数的和
void init(ll MX) {
memset(ji, 0, sizeof(ji));
pris[0] = 0;
top = 0;
for (int i = 2; i <= MX; i++) {
if (!ji[i]) {
pri[++top] = i;
pris[top] = (pris[top - 1] + i) % mod;
}
for (int j = 1; j <= top && 1ll * i * pri[j] <= MX; j++) {
int cur = i * pri[j];
ji[cur] = 1;
if (i % pri[j] == 0)
break;
}
}
}
void add(ll &a, ll b) {
a = (a + b) % mod;
if (a < 0)
a += mod;
return;
}
ll S(ll n, ll m) {
if (n <= 1 || pri[m] > n)
return 0;
ll kt = mp[n];
ll res = (g[kt] - h[kt] - (pris[m - 1] - m + 1)) % mod;
if (res < 0)
res += mod;
if (m == 1)
res += 2;
for (int k = m; k <= top && 1ll * pri[k] * pri[k] <= n; k++) {
ll ans = pri[k];
for (int i = 1; ans * pri[k] <= n; i++, ans *= pri[k]) {
add(res, (1ll * (S(n / ans, k + 1)) * (pri[k] ^ i) % mod + (pri[k] ^ (i + 1))) % mod);
}
}
return res;
}
int main() {
ll n;
while (cin >> n) {
ll fb = sqrt(n);
init(fb);
ll j;
int times = 0;
ll ans;
for (ll i = 1; i <= n; i = j + 1) {
w[++times] = n / i;
j = n / (n / i);
h[times] = (w[times] - 1) % mod;
g[times] = (((w[times] % mod * (w[times] + 1) % mod) % mod * INV2) % mod - 1 + mod) % mod;
mp[w[times]] = times;
}
for (int i = 1; i <= top; i++) {
ll k = 1ll * pri[i] * pri[i];
for (int j = 1; j <= times && k <= w[j]; j++) {
int kt = mp[w[j] / pri[i]];
add(g[j], mod - 1ll * pri[i] * (g[kt] - pris[i - 1]) % mod);
add(h[j], mod - (h[kt] - i + 1) % mod);
}
}
//g[i]-h[i]=w[i]以内
//w[i]表示n/i,mp[n/i]=i,h[i]表示n/i(含)内有多少个质数,g[i]=n/i内的质数之和表示
cout << (S(n, 1) + 1) % mod << endl;
}
}