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();
	}
}
posted @ 2020-08-03 15:37  Cold_Chair  阅读(222)  评论(0编辑  收藏  举报