The Preliminary Contest for ICPC Asia Nanjing 2019 南京网络赛 E. K Sum(杜教筛+欧拉降幂)

标题

有函数
f n ( k ) = ∑ l 1 = 1 n ∑ l 2 = 1 n ⋯ ∑ l k = 1 n g c d ( l 1 , l 2 , ⋯   , l k ) 2 f_{n}(k)=\sum_{l_1=1}^{n}\sum_{l_2=1}^{n}\cdots\sum_{l_k=1}^{n}gcd(l_1,l_2,\cdots,l_k)^2 fn(k)=l1=1nl2=1nlk=1ngcd(l1,l2,,lk)2

∑ i = 2 k f n ( i ) m o d    1 e 9 + 7 \sum_{i=2}^kf_n(i)\mod 1e9+7 i=2kfn(i)mod1e9+7
其中 1 ≤ n ≤ 1 0 9 1\le n\le 10^9 1n109, 2 ≤ k ≤ 1 0 1 0 5 2\le k \le 10^{10^5} 2k10105

思路

第一步我们肯定先对 f n ( k ) f_n(k) fn(k)进行化简,先把 g c d gcd gcd提出来
f n ( k ) = ∑ d = 1 n d 2 ∑ l 1 = 1 n ∑ l 2 = 1 n ⋯ ∑ l k = 1 n [ g c d ( l 1 , l 2 , ⋯   , l k ) = = d ] f_n(k)=\sum_{d=1}^nd^2\sum_{l_1=1}^{n}\sum_{l_2=1}^{n}\cdots\sum_{l_k=1}^{n}[gcd(l_1,l_2,\cdots,l_k)==d] fn(k)=d=1nd2l1=1nl2=1nlk=1n[gcd(l1,l2,,lk)==d]
后面部分都除个 d d d
f n ( k ) = ∑ d = 1 n d 2 ∑ l 1 = 1 n d ∑ l 2 = 1 n d ⋯ ∑ l k = 1 n d [ g c d ( l 1 , l 2 , ⋯   , l k ) = = 1 ] f_n(k)=\sum_{d=1}^nd^2\sum_{l_1=1}^{\frac{n}{d}}\sum_{l_2=1}^{\frac{n}{d}}\cdots\sum_{l_k=1}^{\frac{n}{d}}[gcd(l_1,l_2,\cdots,l_k)==1] fn(k)=d=1nd2l1=1dnl2=1dnlk=1dn[gcd(l1,l2,,lk)==1]
∑ d ∣ g c d ( l 1 , l 2 , ⋯   , l k ) μ ( d ) = [ g c d ( l 1 , l 2 , ⋯   , l k ) = = 1 ] \sum_{d|gcd(l_1,l_2,\cdots,l_k)}\mu(d)=[gcd(l_1,l_2,\cdots,l_k)==1] dgcd(l1,l2,,lk)μ(d)=[gcd(l1,l2,,lk)==1]带入
f n ( k ) = ∑ d = 1 n d 2 ∑ l 1 = 1 n d ∑ l 2 = 1 n d ⋯ ∑ l k = 1 n d ∑ i ∣ g c d ( l 1 , l 2 , ⋯   , l k ) μ ( i ) f_n(k)=\sum_{d=1}^nd^2\sum_{l_1=1}^{\frac{n}{d}}\sum_{l_2=1}^{\frac{n}{d}}\cdots\sum_{l_k=1}^{\frac{n}{d}}\sum_{i|gcd(l_1,l_2,\cdots,l_k)}\mu(i) fn(k)=d=1nd2l1=1dnl2=1dnlk=1dnigcd(l1,l2,,lk)μ(i)
i i i提出有,及枚举1到 n d \frac{n}{d} dn内的倍数,所以有

f n ( k ) = ∑ d = 1 n d 2 ∑ i = 1 n d μ ( i ) ∑ l 1 = 1 n i d ∑ l 2 = 1 n i d ⋯ ∑ l k = 1 n i d 1 f_n(k)=\sum_{d=1}^nd^2\sum_{i=1}^{\frac{n}{d}}\mu(i)\sum_{l_1=1}^{\frac{n}{id}}\sum_{l_2=1}^{\frac{n}{id}}\cdots\sum_{l_k=1}^{\frac{n}{id}}1 fn(k)=d=1nd2i=1dnμ(i)l1=1idnl2=1idnlk=1idn1
后面的部分及 n i d \frac{n}{id} idn k k k次幂即
f n ( k ) = ∑ d = 1 n d 2 ∑ i = 1 n d μ ( i ) ⌊ n i d ⌋ k f_n(k)=\sum_{d=1}^nd^2\sum_{i=1}^{\frac{n}{d}}\mu(i)\left \lfloor \frac{n}{id} \right \rfloor^k fn(k)=d=1nd2i=1dnμ(i)idnk上式等价于
f n ( k ) = ∑ d = 1 n d 2 ∑ i d = 1 n μ ( i ) ⌊ n i d ⌋ k f_n(k)=\sum_{d=1}^nd^2\sum_{id=1}^{n}\mu(i)\left \lfloor \frac{n}{id} \right \rfloor^k fn(k)=d=1nd2id=1nμ(i)idnk
我们令 T = i d T=id T=id带入有
f n ( k ) = ∑ d = 1 n ∑ T = 1 n [ T % d = = 0 ] d 2 μ ( T d ) ⌊ n T ⌋ k f_n(k)=\sum_{d=1}^n\sum_{T=1}^{n}[T\%d==0]d^2\mu(\frac{T}{d})\left \lfloor \frac{n}{T} \right \rfloor^k fn(k)=d=1nT=1n[T%d==0]d2μ(dT)Tnk
这里可以看作枚举的是 1 1 1 n n n中每一个 d d d的倍数,那么我们也等价于枚举 1 1 1 n n n中每个数 T T T的因子
f n ( k ) = ∑ T = 1 n ⌊ n T ⌋ k ∑ d ∣ T d 2 μ ( T d ) f_n(k)=\sum_{T=1}^n\left \lfloor \frac{n}{T} \right \rfloor^k\sum_{d|T}d^2\mu(\frac{T}{d}) fn(k)=T=1nTnkdTd2μ(dT)
然后我们考虑求解设有函数 S ( n ) S(n) S(n), f ( n ) f(n) f(n)
S ( n ) = ∑ i = 1 n f ( i ) = ∑ i = 1 n ∑ d ∣ T d 2 μ ( T d ) S(n)=\sum_{i=1}^nf(i)=\sum_{i=1}^n\sum_{d|T}d^2\mu(\frac{T}{d}) S(n)=i=1nf(i)=i=1ndTd2μ(dT)
对于函数 f ( n ) f(n) f(n) I d 2 Id^2 Id2 μ \mu μ的迪利克雷卷积即
f ( n ) = ( I d 2 ∗ μ ) ( n ) f(n)=(Id^2*\mu)(n) f(n)=(Id2μ)(n)
我们又知道 μ ∗ I = e \mu*I=e μI=e
我们令 g ( n ) = I ( n ) = 1 g(n)=I(n)=1 g(n)=I(n)=1 g g g f f f进行卷积然后对其求和,即用杜教筛
∑ i = 1 n g ∗ f = ∑ i = 1 n I d 2 ( i ) = ∑ i = 1 n i 2 = n ( n + 1 ) ( 2 n + 1 ) 6 \sum_{i=1}^ng*f=\sum_{i=1}^nId^2(i)=\sum_{i=1}^ni^2=\frac{n(n+1)(2n+1)}{6} i=1ngf=i=1nId2(i)=i=1ni2=6n(n+1)(2n+1)
所以这两个函数的卷积的前缀和是很好求的

∑ i = 1 n ∑ d ∣ i g ( d ) f ( i d ) \sum_{i=1}^n\sum_{d|i}g(d)f(\frac{i}{d}) i=1ndig(d)f(di)
对于这个式子是枚举1到n中每个数的因子的,他和枚举1到n中每个数的倍数是等价的那就有
∑ i = 1 n ∑ d ∣ i g ( d ) f ( i d ) = ∑ d = 1 n ∑ i = 1 ⌊ n d ⌋ g ( d ) f ( i ) = ∑ d = 1 n g ( d ) ∑ i = 1 ⌊ n d ⌋ f ( i ) = ∑ d = 1 n g ( d ) S ( ⌊ n d ⌋ ) \sum_{i=1}^n\sum_{d|i}g(d)f(\frac{i}{d})=\sum_{d=1}^n\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}g(d)f(i)=\sum_{d=1}^ng(d)\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}f(i)=\sum_{d=1}^ng(d)S(\left \lfloor \frac{n}{d} \right \rfloor) i=1ndig(d)f(di)=d=1ni=1dng(d)f(i)=d=1ng(d)i=1dnf(i)=d=1ng(d)S(dn)
∑ d = 1 n g ( d ) S ( ⌊ n d ⌋ ) = g ( 1 ) S ( n ) + ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) = ∑ i = 1 n i 2 \sum_{d=1}^ng(d)S(\left \lfloor \frac{n}{d} \right \rfloor)=g(1)S(n)+\sum_{d=2}^ng(d)S(\left \lfloor \frac{n}{d} \right \rfloor)=\sum_{i=1}^ni^2 d=1ng(d)S(dn)=g(1)S(n)+d=2ng(d)S(dn)=i=1ni2
g ( 1 ) S ( n ) = ∑ i = 1 n i 2 − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) g(1)S(n)=\sum_{i=1}^ni^2-\sum_{d=2}^ng(d)S(\left \lfloor \frac{n}{d} \right \rfloor) g(1)S(n)=i=1ni2d=2ng(d)S(dn)
由于 g ( n ) = 1 g(n)=1 g(n)=1,所以
S ( n ) = n ( n + 1 ) ( 2 n + 1 ) 6 − ∑ d = 2 n S ( ⌊ n d ⌋ ) S(n)=\frac{n(n+1)(2n+1)}{6}-\sum_{d=2}^nS(\left \lfloor \frac{n}{d} \right \rfloor) S(n)=6n(n+1)(2n+1)d=2nS(dn)
对于 f f f函数我们要先预处理一部分前缀和这样可以降低杜教筛的复杂度

f f f函数是一个积性函数,显然可以用积性函数线性筛,即记录一个 l o w [ i ] low[i] low[i] l o w [ i ] low[i] low[i]的含义是记录将i唯一分解后最小的质数的次幂,即 l o w [ i ] = p k low[i]=p^k low[i]=pk,那么在线性筛中当 i % p r i m e [ j ] = = 0 i\%prime[j]==0 i%prime[j]==0时, i l o w [ i ] \frac{i}{low[i]} low[i]i l o w [ i ] ∗ p r i m e [ j ] low[i]*prime[j] low[i]prime[j]肯定是互质的,那么就可以通过积性函数的性质互质的两个数 f ( i ) ∗ f ( j ) = f ( i j ) f(i)*f(j)=f(ij) f(i)f(j)=f(ij),所以 f [ i ∗ p r i m e [ j ] ] = f [ i / l o w [ i ] ] ∗ f [ l o w [ i ] ∗ p r i m e [ j ] ] f[i*prime[j]]=f[i/low[i]]*f[low[i]*prime[j]] f[iprime[j]]=f[i/low[i]]f[low[i]prime[j]]。但是还有一种情况就是当 i = = l o w [ i ] i==low[i] i==low[i]时, i i i中不含有其他因子那么有我们要处理一下 f ( p k ) f(p^k) f(pk)这种,通过手写几项就可以发现有递推式 f [ i ∗ p r i m e [ j ] ] = f [ i ] ∗ p r i m e [ j ] f[i*prime[j]]=f[i]*prime[j] f[iprime[j]]=f[i]prime[j],即 f ( p k + 1 ) = f ( p k ) ∗ p f(p^{k+1})=f(p^k)*p f(pk+1)=f(pk)p,这样就可以筛了

再回到原函数 f n ( k ) f_n(k) fn(k)中,有 l a s t = n n T last=\frac{n}{\frac{n}{T}} last=Tnn,那么 f n ( k ) f_n(k) fn(k)就可以分块做有

f n ( k ) = ∑ T = 1 n ( S ( l a s t ) − S ( T − 1 ) ) ⌊ n T ⌋ k f_n(k)=\sum_{T=1}^n(S(last)-S(T-1))\left \lfloor \frac{n}{T} \right \rfloor^k fn(k)=T=1n(S(last)S(T1))Tnk
题目要求的是
∑ i = 2 k f n ( i ) = ∑ T = 1 n ( S ( l a s t ) − S ( T − 1 ) ) ∑ i = 2 k ⌊ n T ⌋ i \sum_{i=2}^kf_n(i)=\sum_{T=1}^n(S(last)-S(T-1))\sum_{i=2}^k\left \lfloor \frac{n}{T} \right \rfloor^i i=2kfn(i)=T=1n(S(last)S(T1))i=2kTni
q = ⌊ n T ⌋ q=\left \lfloor \frac{n}{T} \right \rfloor q=Tn,那么后面就是一个等比数列求和有
∑ i = 2 k f n ( i ) = ∑ T = 1 n ( S ( l a s t ) − S ( T − 1 ) ) q k + 1 − q 2 q − 1 \sum_{i=2}^kf_n(i)=\sum_{T=1}^n(S(last)-S(T-1))\frac{q^{k+1}-q^2}{q-1} i=2kfn(i)=T=1n(S(last)S(T1))q1qk+1q2
注意还有公比为 1 1 1的情况,所以实际上的答案为
∑ i = 2 k f n ( i ) = ∑ T = 1 n ( S ( l a s t ) − S ( T − 1 ) ) q k + 1 − q 2 q − 1 [ q ! = 1 ] + ( S ( l a s t ) − S ( T − 1 ) ) ( k − 1 ) [ q = = 1 ] \sum_{i=2}^kf_n(i)=\sum_{T=1}^n(S(last)-S(T-1))\frac{q^{k+1}-q^2}{q-1}[q!=1]+(S(last)-S(T-1))(k-1)[q==1] i=2kfn(i)=T=1n(S(last)S(T1))q1qk+1q2[q!=1]+(S(last)S(T1))(k1)[q==1]
还有一点值得注意的是他的 k k k很大,在求解 q k + 1 q^{k+1} qk+1次幂的时候要用上欧拉降幂这个时候对输入的 k m o d    1 e 9 + 6 k\mod 1e9+6 kmod1e9+6,而当公比为 1 1 1的时候用的是输入的 k m o d    1 e 9 + 7 k\mod 1e9+7 kmod1e9+7,记录两个 k k k的值

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
const int p=mod-1;
const int inv6=166666668;
bool vis[N];
int prime[N];
long long f[N];
int low[N];
int cnt;
void init()
{
    f[1]=low[1]=1;
    cnt=0;
    for(int i=2; i<N; i++)
    {
        if(!vis[i])
        {
            prime[cnt++]=i;
            f[i]=(1ll*i*i-1+mod)%mod;
            low[i]=i;
        }
        for(int j=0; j<cnt&&i*prime[j]<N; j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                low[i*prime[j]]=low[i]*prime[j];
                if(i==low[i])
                {
                    f[i*prime[j]]=f[i]*prime[j]%mod*prime[j]%mod;
                }
                else
                {
                    f[i*prime[j]]=f[i/low[i]]*f[low[i]*prime[j]]%mod;
                }
                break;
            }
            else
            {
                low[i*prime[j]]=prime[j];
                f[i*prime[j]]=f[i]*f[prime[j]]%mod;
            }
        }
    }
    for(int i=1; i<N; i++)
        f[i]=(f[i-1]+f[i])%mod;
}
map<long long,long long>F;
long long S(long long n)
{
    if(n<N) return f[n];
    if(F.find(n)!=F.end()) return F[n];
    long long sum=n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
    for(long long i=2,last; i<=n; i=last+1)
    {
        last=n/(n/i);
        sum=(sum-(last-i+1)%mod*S(n/i)%mod+mod)%mod;
    }
    F[n]=sum;
    return sum;
}
long long quickmod(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b%2==1)
            ans=ans*a%mod;
        a=a*a%mod;
        b=b/2;
    }
    return ans;
}
char str[100005];
int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d%s",&n,str);
        long long k1=0;
        long long k2=0;
        int len=strlen(str);
        for(int i=0;i<len;i++)
        {
            k1=k1*10+str[i]-'0';
            k1%=p;
            k2=k2*10+str[i]-'0';
            k2%=mod;
        }
        long long ans=0;
        for(int i=1,last;i<=n; i=last+1)
        {
            last=n/(n/i);
            if((n/i)!=1)
            {
                ans=(ans+(S(last)-S(i-1)+mod)%mod*(quickmod(n/i,k1+1)%mod-1ll*(n/i)*(n/i)%mod+mod)%mod*quickmod(n/i-1,mod-2)%mod)%mod;
            }
            else
            {
                ans=(ans+(S(last)-S(i-1)+mod)%mod*((k2-1+mod)%mod)%mod)%mod;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值