https://gmoj.net/senior/#main/show/5031
题解:
只是做这题当然是不用DGF的,可以直接上组合数。
定义(f)函数的导为(f(n)'=f(n) imes omega(n))
其中(omega(n))为(n)分解质因数后指数和。
那么就可以得出(ln(F))和(exp(F))。
(ln(F)'=F'/F)
(ln(F)' imes 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]=ksum_{d|n}F[d]*omega(d)*G[n/d])
注意到(omega(1)=0),所以:
(sum_{d|n} G[d]*omega(d)*F[n/d]=ksum_{d|n且d>1}F[d]*omega(d)*G[n/d])
(G[n]*omega(n)*F[1]=ksum_{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("
")
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("
")
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();
}
}