牛客练习赛84 F 牛客推荐系统开发之下班
牛客推荐系统开发之下班
https://ac.nowcoder.com/acm/contest/11174/F
好像只有我的公式是长这样的,但是跑的最快。
考虑到
其中,*是狄利克雷卷积,I是单位1。
进行杜教筛即可。
这里提一点,一个函数和mu卷是可以O(n)的求的。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
const int N = 5e6 + 100;
const int M = N - 100;
const int MOD = 1e9 + 9;
int tot;
int pri[N], f[N];
bool is_prime[N];
void upd(int &a, int b) {
a += b; if (a >= MOD) a -= MOD;
}
void get_phi() {
memset(is_prime, true, sizeof(is_prime));
for (int i = 2; i < N; i++) {
if (is_prime[i]) pri[tot++] = i;
for (int j = 0; j < tot && i * pri[j] < N; j++) {
is_prime[i * pri[j]] = false;
if (i % pri[j] == 0) break;
}
}
f[1] = 1;
for (int i = 2; i <= M; i++) {
f[i] = f[i - 1] + f[i - 2];
if (f[i] >= MOD) f[i] -= MOD;
}
for (int i = 0; i < tot; i++) {
for (int j = M / pri[i]; j; j--) {
upd(f[j * pri[i]], MOD - f[j]);
}
}
for (int i = 1; i <= M; i++) upd(f[i], f[i - 1]);
}
map<int, int> sf;
int fu[5][5], co[5][5], res[5][5];
void cal(int a[][5], int b[][5]) {
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
fu[i][j] = (fu[i][j] + 1LL * a[i][k] * b[k][j]) % MOD;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
a[i][j] = fu[i][j];
fu[i][j] = 0;
}
}
}
ll get(ll n) {
n--;
res[0][1] = res[1][0] = co[1][1] = 0;
res[0][0] = res[1][1] = co[0][0] = co[0][1] = co[1][0] = 1;
while (n > 0) {
if (n & 1) cal(res, co);
cal(co, co); n /= 2;
}
return res[0][0];
}
ll F(ll n) {
if (n <= M) return f[n];
if (sf.count(n)) return sf[n];
int ans = get(n + 2) - 1;
for (int l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
ans = (ans - (r - l + 1LL) * F(n / l)) % MOD;
}
ans = (ans % MOD + MOD) % MOD;
return sf[n] = ans;
}
ll qpow(ll x, ll n) {
ll res = 1;
while (n > 0) {
if (n & 1) res = res * x % MOD;
x = x * x % MOD;
n /= 2;
}
return res;
}
int n, k;
int a, b = 1;
int main() {
//freopen("0.txt", "r", stdin);
get_phi();
scanf("%d%d", &n, &k);
ll ans = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ll co = qpow(n / l, k);
ans = (ans + co * (F(r) - F(l - 1))) % MOD;
}
ans = (ans % MOD + MOD) % MOD;
printf("%lld\n", ans);
return 0;
}
小红书公司福利 935人发布