2019 西安邀請賽 B Product

https://nanti.jisuanke.com/t/39269

題意:

給你n,m,modn,m,mod讓你求i=1nj=1nk=1nmgcd(i,j)[kgcd(i,j)]% mod\prod\limits_{i=1}^{n}\prod\limits_{j=1}^{n}\prod\limits_{k=1}^{n}m^{\gcd(i,j)[k|\gcd(i,j)]}\%\ mod

思路:

由於相乘的的公式不好化,我們可以先把次冪提出來這樣就把公式化成這樣mi=1nj=1nk=1ngcd(i,j)[kgcd(i,j)]%φ(mod)% modm^{\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\sum\limits_{k=1}^{n}\gcd(i,j)[k|gcd(i,j)]\%\varphi(mod)}\%\ mod
因爲對指數求和取模,所以要用到歐拉降冪,因爲modmod是素數所以直接對φ(mod)\varphi(mod)取模即可
那麼我們的任務就變成了化簡i=1nj=1nk=1ngcd(i,j)[kgcd(i,j)]%φ(mod)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\sum\limits_{k=1}^{n}\gcd(i,j)[k|gcd(i,j)]\%\varphi(mod)
我們把gcdgcd提出來後
g=1ngk=1n[kg]i=1n/gj=1n/g[gcd(i,j)==1]\sum\limits_{g=1}^{n}g\sum\limits_{k=1}^{n}[k|g]\sum\limits_{i=1}^{n/g}\sum\limits_{j=1}^{n/g}[\gcd(i,j) == 1]
g=1ngkgi=1n/gj=1n/g[gcd(i,j)==1]\sum\limits_{g=1}^{n}g\sum\limits_{k|g}\sum\limits_{i=1}^{n/g}\sum\limits_{j=1}^{n/g}[\gcd(i,j) == 1]
kk提到外面
k=1nkg=1n/kgi=1n/gkj=1n/gk[gcd(i,j)==1]\sum\limits_{k=1}^{n}k\sum\limits_{g=1}^{n/k}g\sum\limits_{i=1}^{n/gk}\sum\limits_{j=1}^{n/gk}[\gcd(i,j) == 1]
後面的根據莫比烏斯反演
k=1nkg=1n/kgi=1n/kgj=1n/kgdgcd(i,j)μ(d)\sum\limits_{k=1}^{n}k\sum\limits_{g=1}^{n/k}g\sum\limits_{i=1}^{n/kg}\sum\limits_{j=1}^{n/kg}\sum\limits_{d|gcd(i,j)}\mu(d)
我們在把μ\mu提到外面
k=1nkg=1n/kgd=1n/kgμ(d)i=1n/kgdj=1n/kgd1\sum\limits_{k=1}^{n}k\sum\limits_{g=1}^{n/k}g\sum\limits_{d=1}^{n/kg}\mu(d)\sum\limits_{i=1}^{n/kgd}\sum\limits_{j=1}^{n/kgd}1
k=1nkg=1n/kgd=1n/kgμ(d)nkdg2\sum\limits_{k=1}^{n}k\sum\limits_{g=1}^{n/k}g\sum\limits_{d=1}^{n/kg}\mu(d)\lfloor\frac{n}{kdg}\rfloor^2
我們令T=kdgT=kdg
T=1nnT2kTkdTkdμ(Tkd)\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor^2\sum\limits_{k|T}k\sum\limits_{d|\frac{T}{k}}d \cdot \mu(\frac{T}{kd})
後面的kTkdTkdμ(Tkd)\sum\limits_{k|T}k\sum\limits_{d|\frac{T}{k}}d\cdot \mu(\frac{T}{kd})IdIdμ()Id*Id*\mu(*爲迪利克雷卷積)
因爲Idμ=φId*\mu=\varphi
所以原式可以化成T=1nnT2kTkφ(Tk)\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor^2\sum\limits_{k|T}k \cdot \varphi(\frac{T}{k})
我們令F(n)=knkφ(Tk)F(n)=\sum\limits_{k|n}k\cdot \varphi(\frac{T}{k})
因爲F(n)=IdφF(n) = Id * \varphi
那麼我們把F(n)g(n)=1F(n)卷積上一個g(n)=1後
Fg=Idφ1=IdId=knknk=knnF*g=Id*\varphi *1=Id*Id=\sum\limits_{k|n}k\cdot \frac{n}{k}=\sum\limits_{k|n}n
那麼F(n)F(n)的前綴和就可以用杜教篩
g(1)S(n)=i=1nkiii=2nS(ni)g(1)S(n)=\sum\limits_{i=1}^{n}\sum\limits_{k|i}i-\sum\limits_{i=2}^{n}S(\lfloor\frac{n}{i}\rfloor)
對於i=1nkii\sum\limits_{i=1}^{n}\sum\limits_{k|i}i
我們把kk提到前面 i=1nij=1n/ij,\sum\limits_{i=1}^{n}i\sum\limits_{j=1}^{n/i}j,這樣可以用分塊快速求出結果
那麼杜教篩就爲S(n)=i=1nij=1n/iji=2nS(ni)S(n)=\sum\limits_{i=1}^{n}i\sum\limits_{j=1}^{n/i}j-\sum\limits_{i=2}^{n}S(\lfloor\frac{n}{i}\rfloor)
原式爲:T=1nnT2F(T)\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor^2F(T)
Tn23F(n)knkφ(nk)T\leq n^{\frac{2}{3}} F(n)爲\sum\limits_{k|n}k\cdot \varphi(\frac{n}{k})
Tn23F(n)當T\geq n^{\frac{2}{3}}時 F(n) 用杜教篩求
那麼問題來了,怎麼快速求knkφ(nk)\sum\limits_{k|n}k\cdot \varphi(\frac{n}{k})
如果用nlog(n)nlog(n)那就穩T了
參照這篇博客

https://www.90yang.com/2019-icpc-xian-invitation-b-product/

我們設G(pn)kpnkφ(nk)=pipj=pnpiφ(pj)G(p^n)爲\sum\limits_{k|p^n}k\cdot \varphi(\frac{n}{k})=\sum\limits_{p^i\cdot p^j=p^n}p^i\cdot \varphi(p^j)
pipj=pnpiφ(pj)=p0φ(pn)+p1φ(pn1)+p2φ(pn2)+...+pnφ(p0)\sum\limits_{p^i\cdot p^j=p^n}p^i\cdot \varphi(p^j)=p^0\cdot \varphi(p^{n})+p^1\cdot \varphi(p^{n-1})+p^2\cdot \varphi(p^{n-2})+...+p^n\cdot \varphi(p^{0})
因爲φ(x)=xi(11pi)\varphi(x)=x\prod\limits_{i}(1-\frac{1}{p_i})
帶入上式中,得到G(pn)=(n+1)pnnpn1G(p^n) = (n+1)p^n-np^{n-1}
我們定義三個中間變量,
g,phi,sg, phi, s
gg(n)snpeg(pe)phinpeφ(pe)g代表g(n)\\ s代表n最小的質因子p及其指數e的g(p^e)\\ phi代表n最小的質因子p及其指數e的\varphi(p^e)
那麼當我們進行線性篩時,

 F[1] = g[1] = phi[1] = 1;
    for (ll i = 2; i <= maxn; i ++) {
        if(!mark[i]) {
            prim[++tot] = i;
            phi[i] = i - 1;
            g[i] = s[i] = 2*i-1;
        }
        for (ll j = 1; j <= tot; j ++) {
            if(i * prim[j] > maxn) break;
            mark[i * prim[j]] = 1;
            if(i % prim[j] == 0) {
                s[i*prim[j]] = (s[i] + phi[i] + 0ll) * prim[j];
                phi[i * prim[j]] = phi[i] * prim[j];
                g[i*prim[j]] = g[i] / s[i] * s[i*prim[j]];
                break;
            }   
            phi[i * prim[j]] = phi[prim[j]];
            s[i*prim[j]] = s[prim[j]];
            g[i*prim[j]] = g[i] * s[i*prim[j]];
        }
        F[i] = (F[i-1] + g[i]) % p;
    }

jij根據線性篩的性質,下面的j是i*j這個數的最小質因子

phiijphi[ij]=phi[j]ijphi[ij]=phi[i]j()對於phi\\ 當i不包含j時phi[i*j]=phi[j]\\ 當i包含j時phi[i*j]=phi[i]*j(歐拉函數的性質)

sij,s[ij]=s[j]ij,s[ij]=(s[i]+phi[i])js[i]=(e+1)peepe1s[i]+phi[i]=(e+2)pe(e+1)pe1(s[i]+phi[i])j=(e+2)pe+1(e+1)pes[ij]j對於s\\ 當i不包含j時,s[i*j]=s[j]\\ 當i包含j時,s[i*j]=(s[i]+phi[i])*j\\ s[i] = (e+1)p^{e} - e \cdot p ^ {e-1}\\ s[i]+phi[i]=(e+2)p^e-(e+1)\cdot p^{e-1}\\ (s[i]+phi[i])\cdot j=(e+2)p^{e+1}-(e+1)\cdot p^{e}\\ 這樣s[i*j]就把j的最小質因子的個數就加了一個

gijg[ij]=g[i]s[ij]ijg[ij]=g[i]/s[i]s[ij]對於g\\ 根據積性函數的性質\\ 當i不包括j時,g[i\cdot j]=g[i]\cdot s[i\cdot j]\\ 當i包括j時,g[i\cdot j]=g[i]/s[i]\cdot s[i\cdot j]

這樣就可以預處理前綴和了

AC代碼:

#include<bits/stdc++.h>

using namespace std;

#define ll long long
const int maxn = 1e6 + 5;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
typedef pair<int, int> psi;

int prim[maxn+30];
ll phi[maxn+30];
int tot;
bool mark[maxn+30];
ll mod, n, m, p;
ll F[maxn+30], q[maxn+30], s[maxn+30], g[maxn+30];
map<ll, ll> mp;

ll Pow(ll a, ll b, ll p) {
    ll res = 1;
    a %= p;
    while(b) {
        if(b & 1) res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}

void init() {
    F[1] = g[1] = phi[1] = 1;
    for (ll i = 2; i <= maxn; i ++) {
        if(!mark[i]) {
            prim[++tot] = i;
            phi[i] = i - 1;
            g[i] = s[i] = 2*i-1;
        }
        for (ll j = 1; j <= tot; j ++) {
            if(i * prim[j] > maxn) break;
            mark[i * prim[j]] = 1;
            if(i % prim[j] == 0) {
                s[i*prim[j]] = (s[i] + phi[i] + 0ll) * prim[j];
                phi[i * prim[j]] = phi[i] * prim[j];
                g[i*prim[j]] = g[i] / s[i] * s[i*prim[j]];
                break;
            }   
            phi[i * prim[j]] = phi[prim[j]];
            s[i*prim[j]] = s[prim[j]];
            g[i*prim[j]] = g[i] * s[i*prim[j]];
        }
        F[i] = (F[i-1] + g[i]) % p;
    }
}

inline ll GetSum(ll n) {
    return n * (n+1) / 2 % p;
}

inline ll GetRes(ll n) {
    ll res = 0;
    for (ll l = 1, r; l <= n; l = r + 1) {
        r = n / (n / l);
        res = (res + (GetSum(r) - GetSum(l-1)) * GetSum(n/l) % p) % p;
    }
    return res;
}

inline ll GetS(ll n) {
    if(n <= maxn) return F[n];
    if(mp[n]) return mp[n];
    ll res = GetRes(n);
    for (ll l = 2, r; l <= n; l = r + 1) {
        r = n / (n / l);
        res = (res - GetS(n/l) * (r-l+1) % p) % p;
    }
    res = (res + p) % p;
    return mp[n] = res;
}

ll solve(ll n) {
    ll res = 0;
    for (ll l = 1, r; l <= n; l = r + 1) {
        r = n / (n / l);
        res = (res + (n/l) * (n/l) % p * (GetS(r) - GetS(l-1))) % p;
    }
    return (res+p)%p;
}

int main(int argc, char *args[]) {
    scanf("%lld %lld %lld", &n, &m, &mod);
    p = mod - 1;
    init();
    ll res = solve(n);
    printf("%lld\n", Pow(m, res, mod));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章