5031. 【NOI2017模拟3.27】B (k次狄利克雷卷积)
https://gmoj.net/senior/#main/show/5031
题解:
只是做这题当然是不用DGF的,可以直接上组合数。
定义\(f\)函数的导为\(f(n)'=f(n)\times \omega(n)\)
其中\(\omega(n)\)为\(n\)分解质因数后指数和。
那么就可以得出\(ln(F)\)和\(exp(F)\)。
\(ln(F)'=F'/F\)
\(ln(F)' \times F=F'\)
\(\sum_{d|n} ln(F)[d] * \omega(d) * F[n/d]=F[n]*\omega(n)\)
\(ln(F)[n]*\omega(n)=F[n]*\omega(n)-\sum_{d|n且d<n} ln(F)[d] * \omega(d) * F[n/d]\)
\((e^F)'=e^{F}*F'\)
\(exp(F)[n]*\omega(n)=\sum_{d|n}exp(F)[d]*F[n/d]*\omega(n/d)\)
注意\(ln\)后\(F[1]=0\),所以:
\(exp(F)[n]*\omega(n)=\sum_{d|n且d<n}exp(F)[d]*F[n/d]*\omega(n/d)\)
也可以直接推\(G=F^k\)这种东西:
\(G=F^k\)
\(ln(G)=kln(F)\)
\(G'/G=kF'/F\)
\(G'F=kF'G\)
\(\sum_{d|n} G[d]*\omega(d)*F[n/d]=k\sum_{d|n}F[d]*\omega(d)*G[n/d]\)
注意到\(\omega(1)=0\),所以:
\(\sum_{d|n} G[d]*\omega(d)*F[n/d]=k\sum_{d|n且d>1}F[d]*\omega(d)*G[n/d]\)
\(G[n]*\omega(n)*F[1]=k\sum_{d|n且d>1}F[d]*\omega(d)*G[n/d]-\sum_{d|n且d<n} G[d]*\omega(d)*F[n/d]\)
注意:
同多项式的\(ln、exp\),做之前的多项式的常数项必须是\(1\),不然要把它变成\(1\)。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int mo = 1e9 + 7;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
const int N = 1e5 + 5;
int bz[N], p[N], p0, zs[N];
void sieve(int n) {
fo(i, 2, n) {
if(!bz[i]) p[++ p0] = i, zs[i] = 1;
for(int j = 1; i * p[j] <= n; j ++) {
int k = i * p[j]; bz[k] = 1;
zs[k] = zs[i] + 1;
if(i % p[j] == 0) {
break;
}
}
}
}
int T, n, k;
vector<int> d[N];
#define si size()
ll a[N], f[N], g[N], h[N];
void work() {
scanf("%d %d", &n, &k);
fo(i, 1, n) scanf("%lld", &a[i]);
fo(i, 1, n) d[i].clear();
fo(i, 1, n) fo(j, 1, n / i) d[i * j].push_back(i);
h[1] = 0;
fo(i, 2, n) {
h[i] = zs[i];
ff(_j, 0, d[i].si) {
int j = d[i][_j];
if(j < i) h[i] = (h[i] - h[j]) % mo;
}
}
fo(i, 1, n) h[i] = h[i] * k % mo;
g[1] = 1;
fo(i ,2, n) {
g[i] = 0;
ff(_j, 0, d[i].si) {
int j = d[i][_j];
if(j < n) g[i] = (g[i] + g[j] * h[i / j]) % mo;
}
g[i] = g[i] * ksm(zs[i], mo - 2) % mo;
}
fo(i, 1, n) {
ll ans = 0;
ff(_j, 0, d[i].si) {
int j = d[i][_j];
ans = (ans + a[j] * g[i / j]) % mo;
}
ans = (ans % mo + mo) % mo;
pp("%lld ", ans);
}
hh;
}
int main() {
freopen("b.in", "r", stdin);
freopen("b.out", "w", stdout);
sieve(1e5);
scanf("%d", &T);
fo(ii, 1, T) {
work();
}
}
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int mo = 1e9 + 7;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
const int N = 1e5 + 5;
int bz[N], p[N], p0, zs[N];
void sieve(int n) {
fo(i, 2, n) {
if(!bz[i]) p[++ p0] = i, zs[i] = 1;
for(int j = 1; i * p[j] <= n; j ++) {
int k = i * p[j]; bz[k] = 1;
zs[k] = zs[i] + 1;
if(i % p[j] == 0) {
break;
}
}
}
}
int T, n, k;
vector<int> d[N];
#define si size()
ll a[N], f[N], g[N];
void work() {
scanf("%d %d", &n, &k);
fo(i, 1, n) scanf("%lld", &a[i]);
fo(i, 1, n) d[i].clear();
fo(i, 1, n) fo(j, 1, n / i) d[i * j].push_back(i);
g[1] = 1;
fo(i, 2, n) {
g[i] = 0;
ff(_j, 0, d[i].si) {
int j = d[i][_j];
if(j > 1) g[i] = (g[i] + zs[j] * g[i / j] % mo * k) % mo;
if(j < i) g[i] = (g[i] - g[j] * zs[j] % mo) % mo;
}
g[i] = g[i] * ksm(zs[i], mo - 2) % mo;
}
fo(i, 1, n) {
ll ans = 0;
ff(_j, 0, d[i].si) {
int j = d[i][_j];
ans = (ans + a[j] * g[i / j]) % mo;
}
ans = (ans % mo + mo) % mo;
pp("%lld ", ans);
}
hh;
}
int main() {
freopen("b.in", "r", stdin);
freopen("b.out", "w", stdout);
sieve(1e5);
scanf("%d", &T);
fo(ii, 1, T) {
work();
}
}