题目大意:
他突然想算这么一个式子,给出 f(i),1≤i≤n ,要求算
g(i)=∑i1∣i∑i2∣i1∑i3∣i2⋯∑ik∣ik−1f(ik) mod 1000000007 (1≤i≤n,ij∈N+)
题解:
设c(i)为i经过k轮变换后为1的方案数。
那么显然可以这样求g(i*j) += f(i) * c(j) (1 <= j <= ⌊n/i⌋).
由c(i)的性质很容易想到它是一个积性函数,那么我们就可以线筛它了。
若i=∏pqkk
c(i)=∏c(pqkk)
所以现在要求c(pq)
我们可以用挡板问题的思想来快速求c(pq)。
等价于有q+1个球,有一个必须单独放一个箱子里,其余的放进k-1个箱子,每个箱子不一定要放球。
则c(pq)=Cqq+k+1
k辣么大,怎么办?
Lucas定理:
=Cn mod pm mod p∗C⌊n/p⌋⌊m/p⌋(mod p)
此题当中套公式可得:
c(pq)=Cq(q+k+1) mod p
于是此题解决。
Code:
#include<cstdio>
#include<cstring>
#define ll long long
#define fo(i, x, y) for(ll i = x; i <= y; i ++)
using namespace std;
const ll mo = 1e9 + 7;
const ll Maxn = 500005;
char ch[1000005];
ll fac[35], nf[35];
bool bz[Maxn]; ll p[Maxn], c[Maxn], d[Maxn], z[Maxn];
ll n, m, f[Maxn], s[Maxn];
ll ksm(ll x, ll y) {
ll s = 1;
while(y) {
if(y & 1) s = (s * x) % mo;
x = (x * x) % mo; y /= 2;
}
return s;
}
ll C(ll n, ll m) {
ll s = 1;
fo(i, n - m + 1, n) s = (s * i) % mo;
return s * nf[m] % mo;
}
int main() {
fac[0] = 1; fo(i, 1, 30) fac[i] = (fac[i - 1] * i) % mo;
fo(i, 0, 30) nf[i] = ksm(fac[i], mo - 2);
scanf("%lld", &n);
scanf("%s", ch + 1);
ll lc = strlen(ch + 1);
ll yu = 0;
fo(i, 1, lc) {
yu = yu * 10 + ch[i] - 48;
yu %= mo;
}
fo(i, 1, n) scanf("%lld", &f[i]);
c[1] = 1;
fo(i, 2, n) {
if(!bz[i]) p[++ p[0]] = i, c[i] = C(yu, 1), d[i] = i, z[i] = 1;
fo(j, 1, p[0]) {
ll k = i * p[j];
if(k > n) break;
bz[k] = 1;
if(i % p[j] == 0) {
z[k] = z[i] + 1;
d[k] = d[i] * p[j];
c[k] = c[k / d[k]] * C(yu + z[k] - 1, z[k]) % mo;
break;
}
z[k] = 1;
d[k] = p[j];
c[k] = c[i] * c[p[j]] % mo;
}
}
fo(i, 1, n) fo(j, 1, n / i) s[i * j] = (s[i * j] + f[i] * c[j]) % mo;
fo(i, 1, n) printf("%lld ", s[i]);
}