1. 程式人生 > >【51nod 1847】奇怪的數學題

【51nod 1847】奇怪的數學題

fin inline 題目 names 51nod str true 處理 其中

題目描述

給出 N,K ,請計算下面這個式子:
\(∑_{i=1}^N∑_{j=1}^Nsgcd(i,j)^k\)
其中,sgcd(i, j)表示(i, j)的所有公約數中第二大的,特殊地,如果gcd(i, j) = 1, 那麽sgcd(i, j) = 0。
考慮到答案太大,請輸出答案對2^32取模的結果.
1≤N≤109,1≤K≤50
樣例解釋:
因為gcd(i, j)=1時sgcd(i,j)=0對答案沒有貢獻,所以我們只考慮gcd(i,j)>1的情況.
當i是2時,j是2時,sgcd(i,j)=1,它的K次方是1
當i是2時,j是4時,sgcd(i,j)=1,它的K次方是1
當i是3時,j是3時,sgcd(i,j)=1,它的K次方是1

當i是4時,j是2時,sgcd(i,j)=1,它的K次方是1
當i是4時,j是4時,sgcd(i,j)=2,它的K次方是8
當i是5時,j是5時,sgcd(i,j)=1,它的K次方是1

解題思路

設minp(x)表示x最小的質因子(當x等於1時,minp(x)為0,當x質數時,minp(x)為1)。
於是
\[∑_{i=1}^n∑_{j=1}^nsgcd(i,j)^k\]
\[=\sum_{d=2}^{n}\frac{d}{minp(d)}∑^{\lfloor {\frac{n}{d}} \rfloor}_{i=1}∑^{\lfloor {\frac{n}{d}} \rfloor}_{j=1}[sgcd(i,j)==1]\]


\[=\sum_{d=2}^{n}\dfrac{d}{minp(d)}(2∑^{\lfloor {\frac{n}{d}} \rfloor}_{i=1}φ(i)?1)\]
對於\(phi(i)\)的前綴和就可以直接杜教篩。
至於如何求出\(\dfrac{d}{minp(d)}\)
\(d>\sqrt n 且 d為質數\)時,\(\dfrac{d}{minp(d)}\)為1。
這個就可以通過求\(>\sqrt n\)的質數來得出。
我們設
\(F(i,j)表示在[1,j]中,不能被前i個質數整除的數的K次方和\)
\(H(i,j)表示在[1,j]中,不能被前i個質數整除的數的個數\)

\(G(i,j)表示所有x∈[1,j],minp(x)≤p_i,\frac{d}{minp(d)}^K的和\)
於是,我們可以的出一個遞推式
\(F(i,j)=F(i-1,j)-p_i^kF(i-1,\lfloor\dfrac{j}{p_i}\rfloor)\)
\(H(i,j)=H(i-1,j)-H(i-1,\lfloor\dfrac{j}{p_i}\rfloor)\)
\(G(i,j)=G(i-1,j)+F(i-1,\lfloor\dfrac{j}{p_i}\rfloor)\)
答案就是\(H(\sqrt n以內質數個數,n)+G(\sqrt n以內質數個數,n)\)
然後我們發現,當\(p_i>j\)時,F(i,j)=1,H(i,j)=1;
\(p_i^2>j\)
\(F(i,j)=F(i-1,j)-p_i^k\)
\(H(i,j)=H(i-1,j)-1\)
\(G(i,j)=G(i-1,j)+1\)
因為j只有\(\sqrt n\)種取值,我們直接預處理出每種取值,然後直接遞推。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
const long long inf=2147483647;
const int mo=1e9+7;
const int N=1000005;
const int M=55;
using namespace std;
typedef unsigned int uint;
#define sqr(x) ((x)*(x))
long long _n[N],num,p[N],qn,n,m,SP[N],v1[N],phi[N],nphi[N],nn;
uint F[N],G[N],H[N],lu[N],mi[N],smi[N],s[M][M],S[M],ans,Smi[N];
bool bz[N];
uint poww(uint x,uint y)
{
    uint s=1;
    for(;y;y>>=1,x=x*x)
        if(y&1) s=s*x;
    return s;
}
void pre_P()
{
    mi[1]=phi[1]=1;
    for(int i=2;i<=qn;i++)
    {
        if(!bz[i])
        {
            p[++p[0]]=i,phi[i]=i-1,mi[i]=poww(i,m),smi[p[0]]=smi[p[0]-1]+mi[i];
        }
        for(int j=1;j<=p[0];j++)
        {
            int k=i*p[j];
            if(k>qn) break;
            bz[k]=true;
            mi[k]=mi[i]*mi[p[j]];
            if(i%p[j]==0)
            {
                phi[k]=phi[i]*p[j];
                break;
            }
            else phi[k]=phi[i]*(p[j]-1);
        }
    }
    for(int i=1;i<=qn;i++) Smi[i]=Smi[i-1]+mi[i],phi[i]+=phi[i-1];
}
void pre_STR()
{
    for(int i=0;i<=m;i++) s[i][i]=1;
    for(int i=1;i<=m;i++)
        for(int j=1;j<i;j++) s[i][j]=s[i-1][j-1]+s[i-1][j]*(i-1);
}
uint get_P(uint n,uint k)
{
    uint val=1;
    for(uint i=n;i>=n-k+1;i--)
        if(i%k==0) val*=i/k; 
        else val*=i;
    return val;
}
void pre()
{
    for(uint i=1,last=1;i<=n;i=last+1) last=n/(n/i),_n[++num]=n/i;
    reverse(_n+1,_n+1+num);

    pre_P(),pre_STR();
    for(int i=1;i<=num;i++)
    {
        H[i]=_n[i];
        if(_n[i]<=qn)
        {
            F[i]=Smi[_n[i]];
            continue;
        }
        S[0]=_n[i];
        for(int k=1;k<=m;k++)
        {
            S[k]=get_P(_n[i]+1,k+1);
            for(int j=0;j<k;j++) S[k]-=((k-j)&1?-1:1)*s[k][j]*S[j];
        }
        F[i]=S[m];
    }
}
uint get_F(long long i,long long j)
{
    long long k;
    k=j<=qn?j:(num-n/j+1);
    return (!i || sqr(p[i])<=j)?F[k]:(p[i]<=j?(F[k]-smi[i]+smi[lu[k]]):1);
}
uint get_H(long long i,long long j)
{
    long long k;
    k=j<=qn?j:(num-n/j+1);
    return (!i || sqr(p[i])<=j)?H[k]:(p[i]<=j?(H[k]-i+lu[k])%mo:1);
}
uint Sphi(int n)
{
    if(n<=qn) return phi[n];
    if(nphi[nn/n]) return nphi[nn/n];
    uint ans=(n&1)?((n+1)>>1)*n:(n>>1)*(n+1);
    for(int i=2,last=1;i<=n;i=last+1)
    {
        last=n/(n/i);
        ans-=Sphi(n/i)*(last-i+1);
    }
    return nphi[nn/n]=ans;
}
int main()
{
    scanf("%lld%lld",&n,&m),qn=sqrt(n);
    pre();
    for(int i=1;i<=p[0];i++)
    {
        for(int j=num;j>=1;j--)
        {
            F[j]-=mi[p[i]]*get_F(i-1,_n[j]/p[i]);
            G[j]+=get_F(i-1,_n[j]/p[i]);
            H[j]-=get_H(i-1,_n[j]/p[i]);
            lu[j]=i;
            if(i==p[0] || sqr(p[i+1])>_n[i])
                v1[j]=G[j]+H[j]-1;
            if(sqr(p[i])>_n[j-1])
            {
                v1[j]=G[j]+H[j]-1;
                break;
            }
        }
    }
    v1[2]=1;
    if(_n[3]==3) v1[3]=2;
    ans=0;
    nn=n;
    for(int i=2;i<=num;i++)
        ans=ans+(v1[i]-v1[i-1])*(2*Sphi(n/_n[i])-1);
    cout<<ans<<endl;
    return 0;
}

【51nod 1847】奇怪的數學題