計蒜客 2019ICPC 南京網絡賽 E K Sum(莫比烏斯反演 + 杜教篩)

 

 

大致題意:自己看吧……

直接上莫比烏斯反演。

                                 

h(l)=\sum_{d|l}\mu(d)*\frac{l^2}{d^2},,顯然g是一個積性函數,我們考慮用杜教篩求它的前綴和S(n)=\sum_{l=1}^{n}h(l)

                                                             \large \begin{align*} h(l)&=\sum_{d|l}\mu(d)*\frac{l^2}{d^2}\\ h(l)&=(\mu *id^2)(l) \\ (I*h)(l)&=(I*\mu*id^2)(l)\\ (I*h)(l)&=(id^2)(l) \end{align*}

                                        \large \begin{align*} \sum_{l=1}^{n}(I*h)(l)&=\sum_{l=1}^{n}(id^2)(l)\\ \sum_{l=1}^{n}\sum_{i|l}I(l)*h(l/i)&=\frac{n(n+1)(2n+1)}{6}\\ \sum_{i=1}^{n}I(l)*\sum_{l=1}^{\lfloor n/i \rfloor}h(l)&=\frac{n(n+1)(2n+1)}{6}\\ \sum_{i=1}^{n}S(\lfloor n/i \rfloor)&=\frac{n(n+1)(2n+1)}{6}\\ S(n)&=\frac{n(n+1)(2n+1)}{6}-\sum_{i=1}^{n}S(\lfloor n/i \rfloor) \end{align*}

如此杜教篩即可求出S(n)。

考慮求\sum_{k=2}^{K}f_n(k)

                                                 \large \begin{align*} \sum_{k=2}^{K}f_n(k)&=\sum_{k=2}^{K}\sum_{l=1}^{n}{\lfloor \frac{n}{l} \rfloor}^k *h(l)\\ &=\sum_{l=1}^{n}h(l)*\sum_{k=2}^{K}{\lfloor \frac{n}{l} \rfloor}^k \\ &=\sum_{l=1}^{n}h(l)*\frac{q^2*(q^{K-1}-1)}{q-1},q={\lfloor \frac{n}{l} \rfloor} \end{align*}

如此,變成一個等比數列的和,注意需要特殊處理q=1的情況。由於q={\lfloor \frac{n}{l} \rfloor},因此直接對l數論分塊即可。另外,K很大,不過我們可以用歐拉降冪來處理。總的時間複雜度爲具體見代碼:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f3fll
#define eps 1e-6
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;

const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int inv6 = 166666668;

unordered_map<int,int> mp;
int s[N],p[N],sz,n;
char str[N];
bool isp[N];
LL k1,k2;

inline LL qpow(LL x,LL n)
{
    LL res=1;
    while(n)
    {
        if (n&1) res=res*x%mod;
        x=x*x%mod; n>>=1;
    }
    return res;
}

inline void init()
{
    s[1]=1; 
    for(int i=2;i<N;i++)
    {
        if(!isp[i])p[++sz]=i,s[i]=(LL)i*i%mod-1;
         for(int j=1;j<=sz&&i*p[j]<N;j++)
         {
            isp[i*p[j]]=1;
            if(i%p[j]==0)
            {
                s[p[j]*i]=(LL)s[i]*p[j]%mod*p[j]%mod; break;
            } else s[p[j]*i]=(LL)s[p[j]]*s[i]%mod;
        }
    }
    for(int i=2;i<N;i++)
        s[i]=(s[i]+s[i-1])%mod;
}

inline LL S(int n)
{
    if (n<N) return s[n];
    if (mp[n]) return mp[n];
    LL res=(LL)n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
    for(int l=2,r;l<=n;l=r+1)
    {
        int tmp=n/l;
        r=n/tmp; res=(res-(r-l+1)*S(tmp)%mod+mod)%mod;
    }
    return mp[n]=res;
}

inline LL Sum(int q)
{
    if (q==1) return k2-1;
    return (LL)q*q%mod*(qpow(q,k1-1)-1)%mod*qpow(q-1,mod-2)%mod;
}

int main()
{
    init();
    int T; sc(T);
    while(T--)
    {
        LL ans=0;
        sc(n); scanf("%s",str);
        if (strlen(str)<10) k1=k2=atoi(str);
        else 
        {
            k1=k2=0;
            for(int i=0;str[i];i++)
            {
                k1=(k1*10%(mod-1)+str[i]-48)%(mod-1);
                k2=(k2*10%mod+str[i]-48)%mod;
            }
            k1+=mod-1;
        }
        for(int l=1,r,last=0;l<=n;l=r+1)
        {
            int q=n/l; r=n/q; LL tmp=S(r);
            ans=(ans+(tmp-last+mod)*Sum(q)%mod)%mod;
            last=tmp;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章