zoukankan      html  css  js  c++  java
  • 5031. 【NOI2017模拟3.27】B (k次狄利克雷卷积)

    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();
    	}
    }
    
  • 相关阅读:
    不上大学遗撼,上过大学后悔
    消息队列(MSMQ)实现多服务器应用程序之间消息实时交互
    抓取网页源代码
    用asp.net显示在线登陆人数及位置
    原版对XML文档的读写
    C#.NET实现经典排序算法
    深入剖析C#继承机制
    ASP.NET长文章分页
    人民币小写金额转化成大写金额
    GridView和DataFormatString
  • 原文地址:https://www.cnblogs.com/coldchair/p/13426608.html
Copyright © 2011-2022 走看看