facsum (線性篩 積性函數)

facsum

10.20

思路:
對於式子進行分析,前面的Phi就是一個很常規的轉化,變成i^m。後邊一個約數個數,一個Mobius,一個單位函數都是積性函數,所以捲起來也就積性啦(不是積性怎麼做嘛。。)
於是就上線性篩了。
對於 if(i % prime[j] == 0) 的情況,也就是 f[p^k*c] = f[p^k] * f[c]。
所以我們只用考慮 f[p^k] 如何計算,d就是p^i,當 (i <= k-2) 是,n/d 中就會有多個p,那麼mu自然就是0了,不必計算。
所以 f[p^k] = p^k^m * (g[p^k] * mu[1] * 1 + g[p^(k-1)] * mu[p] * p) = p^k^m * (k + 1 + k * (-p))
= p^k^m * (k - kp + 1)。結束
話說打表找規律也不失爲一種很好的方法。

ps:空間限定比較嚴,那些又開mu又開phi什麼的就只有唱歌啦啦啦。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define N 10000010
#define MOD 1000000007
using namespace std;

int n,m;
int prime[N/10], t[N], tot=0;
bool isnot[N];
LL f[N];

int fpow(int a, int b, int p) {
    int ret = 1;
    while( b ) {
        if(b & 1) ret = 1ll * ret * a % p;
        a = 1ll * a * a % p, b >>= 1;
    }
    return ret;
}

int ffp(int a, int b) {
    int ret = 1;
    while( b ) {
        if(b & 1) ret = ret * a;
        a = a * a, b >>= 1;
    }
    return ret;
}

void linear_shaker() {
    memset(isnot, 0, sizeof(isnot));
    f[1] = 1, t[1] = 0;
    for(register int i=2; i<N; ++i) {
        if( !isnot[i] ) prime[++tot] = i, f[i] = 2-i, t[i] = 1;
        for(int j=1; j<=tot && i*prime[j]<N; ++j) {
            int k = i * prime[j];
            isnot[k] = 1;
            if(i % prime[j] == 0){
                t[k] = t[i] + 1;
                f[k] = 1ll * f[k/ffp(prime[j], t[k])] * (t[k]+1-t[k]*prime[j]) % MOD;
                break;
            }
            t[k] = 1;
            f[k] = f[i] * f[prime[j]] % MOD;
        }
    }
}

int main() {
    freopen("facsum.in", "r", stdin);
    freopen("facsum.out", "w", stdout);
    scanf("%d%d", &n, &m);
    linear_shaker();
    int ans = 0;
    for(int i=1; i<=n; ++i){
        ans = (ans + 1ll * fpow(i, m, MOD) * f[i] % MOD) % MOD; 
    }
    printf("%d\n", (ans + MOD) % MOD);
    return 0;
}
發佈了308 篇原創文章 · 獲贊 25 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章