51nod1769(dirichlet convolution)

来源:互联网 发布:什么比价软件好 编辑:程序博客网 时间:2024/06/08 19:17

这个题与上次那个题类似,也是个狄雷克卷积的。
但是这题k很大,不能用快速幂了,那我们就要充分考虑 multiplicative function的性质。具体的过程51nod上面给了很清楚了,主要是给出线性筛部分的代码(这个也是借鉴别人的,侵删)。还有要开读入挂。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;typedef long long LL;const LL mod = 1e9 + 7;const int maxn = 500000 + 5;LL inv[100];LL f[maxn],g[maxn],fg[maxn];LL n,k;LL In(){    char c = getchar();    LL num = 0;    while(!isdigit(c)) c = getchar();    while(isdigit(c)) {        num = num * 10 + c - '0';        if(num >= mod)            num %= mod;        c = getchar();    }    return num;}LL mod_pow(LL a, LL n){    LL ret = 1;    while(n > 0){        if(n & 1) ret = ret * a % mod;        a = a * a % mod;        n >>= 1;    }    return ret;}void Out(LL x){    if(x > 9)        Out(x / 10);    putchar(x % 10 + '0');}void init(){    inv[0] = 1;    for(int i = 1;i < 100;i++){        inv[i] = mod_pow(i,mod - 2);    }}void dirichlet(LL f[],LL g[],LL fg[],int n){    for(int i = 1;i <= n;i++) fg[i] = 0;    for(int i = 1;i * i <= n;i++){        for(int j = i;j * i <= n;j++){            if(i == j) fg[i * j] = (fg[i * j] + f[i] * g[j]) % mod;            else fg[i * j] = (fg[i * j] + f[i] * g[j] + f[j] * g[i]) % mod;        }    }}void solve(int k){    g[1] = 1;    LL *prime = fg;    int tot = 0;    for(int i = 2;i <= n;i++){        if(!prime[i]) prime[tot++] = i,g[i] = k;        for(int j = 0;j < tot && prime[j] * i <= n;j++){            prime[prime[j] * i] = 1;            int r = 1,x = i;            while(x % prime[j] == 0) r++,x /= prime[j];            g[i * prime[j]] = 1LL * g[i] * (r + k - 1) % mod * inv[r] % mod;            if(r != 1) break;        }    }    dirichlet(f, g, fg, (int)n);    for(int i = 1;i <= n;i++){        Out(fg[i]);        if(i < n) putchar(' ');        else putchar('\n');    }}int main(int argc, const char * argv[]) {    init();    n = In();    k = In();    for(int i = 1;i <= n;i++) f[i] = In();    solve(k);    return 0;}
0 0
原创粉丝点击