HDU 5628 Clarke and math

HDU5628

题目描述

给定\(f(i)\),已知\(g(i)=\sum_{i_1|i}\sum_{i_2|i_1}...\sum_{i_k|i_{k-1}}f(i_k)\),求\(g(i)\)

思路

先给出dirichlet卷积的定义:\((f*g)(n)=\sum_{d|n}f(d)g(\frac{n}{d})\),满足结合律。

因此题目要求的东西为\(g=I^k*f\),用快速幂计算即可。

#include <bits/stdc++.h>

using namespace std;
s
typedef long long ll;

const int MAXN = 100000 + 10;
const int MOD = 1000000007;

int n, k;
ll f[MAXN], I[MAXN], e[MAXN];

void init()
{
    for (int i = 1; i <= n; ++i)
        I[i] = 1;
    memset(e, 0, sizeof(e));
    e[1] = 1;
}

void convolution(ll a[], ll b[])
{
    static ll temp[MAXN];
    memset(temp, 0, sizeof(temp));
    for (int i = 1; i * i <= n; ++i) {
        temp[i * i] = (temp[i * i] + a[i] * b[i]) % MOD;
        for (int j = i + 1; j * i <= n; ++j)
            temp[i * j] = (temp[i * j] + a[i] * b[j] + a[j] * b[i]) % MOD;
    }
    memcpy(a, temp, sizeof(temp));
}

int main()
{
    ios::sync_with_stdio(0);
    int T;
    cin >> T;
    while (T--) {
        cin >> n >> k;
        init();
        for (int i = 1; i <= n; ++i)
            cin >> f[i];
        while (k) {
            if (k & 1)
                convolution(e, I);
            convolution(I, I);
            k >>= 1;
        }
        convolution(f, e);
        for (int i = 1; i <= n; ++i)
            cout << f[i] << (i == n ? '\n' : ' ');
    }
}

猜你喜欢

转载自www.cnblogs.com/erro/p/9036830.html