@ljt12138
2017-05-31T07:37:47.000000Z
字数 2054
阅读 1017
给定在上的取值,求函数:
在上的取值。
容易发现,,直接用狄利克雷卷积快速幂即可。
显然,的所有因子在整除关系下构成一个偏序,可以等价地转化为一张带自环而无其他环的图。则从开始的序列与有向无环图上从开始长度为的路径一一对应。
考虑求从开始长度为的路径所有终点位置的和,容易写出方程:
然而这个dp的状态规模是的,考虑原因:存在很长的链是因为可以多次在一个数上重复(即在自环上走)。设为长度为从开始长度为的所有不经过自环的终点位置的和,则:
显然,现在向路径上插入自环。考虑对的贡献,。需要在个位置上插入个自环,用隔板法分析可知为:,因此:
而答案等于的所有因子的的和,即:
自此问题得以解决。复杂度。
#include <bits/stdc++.h>using namespace std;const int MAXN = 100005;struct node {int to, next;} edge[MAXN*20];int head[MAXN], top = 0;inline void push(int i, int j){ edge[++top] = (node){j, head[i]}, head[i] = top; }int n, k;void init(){for (register int i = 1; i <= 100000; i++)for (register int j = 2; j*i <= 100000; j++)push(j*i, i);}long long f[MAXN][20], a[MAXN];const long long mod = 1000000007ll;long long fac[MAXN], inv[MAXN], g[MAXN], g2[MAXN];long long power(int a, long long n){if (n == 0) return 1;long long b = a, ans = 1;for (int k = 0; k <= 30; k++) {if (n&(1ll<<k)) (ans *= b) %= mod;(b *= b) %= mod;}return ans;}inline long long choose(int K, int k){ return fac[K]*inv[k]%mod*inv[K-k]%mod; }void init_c(){inv[0] = 1;for (int i = 1; i <= 100000; i++) inv[i] = (inv[i-1]*power(i, mod-2))%mod;fac[0] = 1;for (int i = 1; i <= 100000; i++) (fac[i] = fac[i-1]*i) %= mod;}void dp(){scanf("%d%d", &n, &k);for (int i = 1; i <= n; i++) scanf("%lld", &f[i][1]);for (int j = 2; j <= 17; j++)for (register int i = 1; i <= n; i++) {f[i][j] = 0;for (register int k = head[i]; k; k = edge[k].next) {int to = edge[k].to;(f[i][j] += f[to][j-1]) %= mod;}}for (register int i = 1; i <= n; i++) {long long ans = 0;for (register int j = 1; j <= 17; j++)(ans += f[i][j]*choose(k-1, j-1)%mod) %= mod;g[i] = ans;}// cerr << endl;memset(g2, 0, sizeof g2);for (register int i = 1; i <= n; i++)for (register int j = 1; j*i <= n; j++)(g2[j*i] += g[i]) %= mod;for (int i = 1; i <= n; i++)printf("%lld ", g2[i]);puts("");}int main(){freopen("b.in", "r" , stdin);freopen("b.out", "w", stdout);init();init_c();int T; scanf("%d", &T);while (T--) dp();return 0;}