以前打的某一场bestcoder的题,不会,今天学习了一下狄雷克卷积(好像没有想象的辣么难,可能写的是模版题)回头写一写。
Dirichletconvolution代码(复杂度O(nlgn))
const int maxn = 10005;
int f[maxn],g[maxn],h[maxn];
for(int i = 1;i * i <= n;i++){
for(int j = i;i * j <= n;j++){
if(i == j) h[i * j] += f[i] * g[j];
else h[i * j] += f[i] * g[j] + f[j] * g[i];
}
}
然后这个题可以看出是f*1k,然后要使用快速幂
代码如下:
//
// main.cpp
// hdu5628
//
// Created by 黄宇凡 on 10/20/16.
// Copyright © 2016 黄宇凡. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 7;
const int maxn = 100000 + 5;
LL f[maxn],g[maxn],h[maxn],tmp[maxn];
int n,k;
void solve(){
while(k){
if(k % 2){
for(int i = 1;i <= n;i++) tmp[i] = 0;
for(int i = 1;i * i <= n;i++){
for(int j = i;i * j <= n;j++){
if(i == j) tmp[i * j] = (tmp[i * j] + g[i] * h[j] % mod) % mod;
else{
tmp[i * j] = (tmp[i * j] + g[i] * h[j] % mod + g[j] * h[i] % mod) % mod;
}
}
}
for(int i = 1;i <= n;i++) h[i] = tmp[i];
}
for(int i = 1;i <= n;i++) tmp[i] = 0;
for(int i = 1;i * i <= n;i++){
for(int j = i;i * j <= n;j++){
if(i == j) tmp[i * j] = (tmp[i * j] + g[i] * g[j] % mod) % mod;
else{
tmp[i * j] = (tmp[i * j] + g[i] * g[j] % mod + g[j] * g[i] % mod) % mod;
}
}
}
for(int i = 1;i <= n;i++) g[i] = tmp[i];
k >>= 1;
}
for(int i = 1;i <= n;i++) tmp[i] = 0;
for(int i = 1;i * i <= n;i++){
for(int j = i;i * j <= n;j++){
if(i == j) tmp[i * j] = (tmp[i * j] + f[i] * h[j] % mod) % mod;
else{
tmp[i * j] = (tmp[i * j] + f[i] * h[j] % mod + f[j] * h[i] % mod) % mod;
}
}
}
for(int i = 1;i <= n;i++) h[i] = tmp[i];
}
int main(int argc, const char * argv[]) {
int T;
cin >> T;
while(T--){
cin >> n >> k;
for(int i = 1;i <= n;i++){
scanf("%I64d",f + i);
g[i] = 1;
h[i] = 0;
}
h[1] = 1;
solve();
for(int i = 1;i <= n;i++){
printf("%I64d%c",h[i],i == n ? '\n' : ' ');
}
}
return 0;
}