hdu6711 Touma Kazusa's function

链接

点击跳转

先来看看求的是什么东西

c i c_i ci表示数字 i i i在给定区间中出现了几次, n = 1 0 7 n=10^7 n=107

∑ i = l r ∑ j = l r φ ( g c d ( a i , a j ) ) l c m ( a i , a j ) \sum_{i=l}^r \sum_{j=l}^r \varphi(gcd(a_i,a_j)) lcm(a_i,a_j) i=lrj=lrφ(gcd(ai,aj))lcm(ai,aj)

= ∑ i = 1 n ∑ j = 1 n φ ( g c d ( i , j ) ) l c m ( i , j ) c i c j = \sum_{i=1}^n \sum_{j=1}^n \varphi(gcd(i,j)) lcm(i,j) c_i c_j =i=1nj=1nφ(gcd(i,j))lcm(i,j)cicj

= ∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ φ ( d ) i j c i d c j d [ ( i , j ) = 1 ] = \sum_{d=1}^n d \sum_{i=1}^{\lfloor\frac{n}{d}\rfloor} \sum_{j=1}^{\lfloor\frac{n}{d}\rfloor} \varphi(d) ij c_{id} c_{jd} [(i,j)=1] =d=1ndi=1dnj=1dnφ(d)ijcidcjd[(i,j)=1]

= ∑ d = 1 n d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ φ ( d ) i j c i d c j d ∑ t ∣ i ∧ t ∣ j μ ( t ) = \sum_{d=1}^n d \sum_{i=1}^{\lfloor\frac{n}{d}\rfloor} \sum_{j=1}^{\lfloor\frac{n}{d}\rfloor} \varphi(d) ij c_{id} c_{jd} \sum_{ t|i \wedge t|j } \mu(t) =d=1ndi=1dnj=1dnφ(d)ijcidcjdtitjμ(t)

= ∑ d = 1 n d φ ( d ) ∑ t = 1 ⌊ n d ⌋ t 2 μ ( t ) ∑ i = 1 ⌊ n d t ⌋ ∑ j = 1 ⌊ n d t ⌋ i j c i d t c j d t = \sum_{d=1}^n d\varphi(d) \sum_{t=1}^{\lfloor\frac{n}{d}\rfloor} t^2 \mu(t) \sum_{i=1}^{\lfloor\frac{n}{dt}\rfloor} \sum_{j=1}^{\lfloor\frac{n}{dt}\rfloor} ij c_{idt} c_{jdt} =d=1ndφ(d)t=1dnt2μ(t)i=1dtnj=1dtnijcidtcjdt

= ∑ d = 1 n d φ ( d ) ∑ t = 1 ⌊ n d ⌋ t 2 μ ( t ) ( ∑ i = 1 ⌊ n d t ⌋ i c i d t ) 2 = \sum_{d=1}^n d\varphi(d) \sum_{t=1}^{\lfloor\frac{n}{d}\rfloor} t^2 \mu(t) ( \sum_{i=1}^{\lfloor\frac{n}{dt}\rfloor} i c_{idt} )^2 =d=1ndφ(d)t=1dnt2μ(t)(i=1dtnicidt)2

换元,令 T = d t T=dt T=dt

= ∑ T = 1 n ∑ d ∣ T d φ ( d ) T 2 d 2 μ ( T d ) ( ∑ i = 1 ⌊ n T ⌋ i c i T ) 2 = \sum_{T=1}^n \sum_{d|T} d\varphi(d) \frac{T^2}{d^2} \mu(\frac{T}{d}) ( \sum_{i=1}^{\lfloor\frac{n}{T}\rfloor} i c_{iT} )^2 =T=1ndTdφ(d)d2T2μ(dT)(i=1TniciT)2

注意看 g ( T ) = ∑ d ∣ T d φ ( d ) T 2 d 2 μ ( T d ) g(T) = \sum_{d|T} d\varphi(d) \frac{T^2}{d^2} \mu(\frac{T}{d}) g(T)=dTdφ(d)d2T2μ(dT)

这玩意是个积性函数,对 T = p k T=p^k T=pk分析发现, g ( T ) = T μ ( T ) g(T) = T\mu(T) g(T)=Tμ(T)

上式接着化简

a n s = ∑ T = 1 n T μ ( T ) ( ∑ i = 1 ⌊ n T ⌋ i c i T ) 2 ans = \sum_{T=1}^n T\mu(T) ( \sum_{i=1}^{\lfloor\frac{n}{T}\rfloor} i c_{iT} )^2 ans=T=1nTμ(T)(i=1TniciT)2

莫队搞一搞

别以为到这里就结束了

卡常简直把我给搞自闭了

必须写的优美否则就会 T L E TLE TLE成狗

我的自闭过程:
在这里插入图片描述

代码

#include <bits/stdc++.h>
#define maxn 100010
#define maxN 10000010
#define rep(_,__) for(_=1;_<=(__);_++)
#define sqr(x) ((x)*(x))
using namespace std;
typedef unsigned int uint;
typedef pair<uint,uint> pr;
uint prime[maxN/10], mu[maxN];
bool mark[maxN];
void shai(uint N)
{
    uint i, j;
    for(i=2;i<=N;i++)mark[i]=false;
    *prime=0;
    mu[1]=1;
    for(i=2;i<=N;i++)
    {
        if(!mark[i])prime[++*prime]=i, mu[i]=-1;
        for(j=1;j<=*prime and i*prime[j]<=N;j++)
        {
            mark[i*prime[j]]=true;
            if(i%prime[j]==0)break;
            mu[i*prime[j]]=-mu[i];
        }
    }
}
uint l[maxn], r[maxn], id[maxn], s[maxN], now, a[maxn], ans[maxn], S;
vector<pr> d[maxn];
void init()
{
    uint i, j;
    shai(10000000);
}
bool cmp(uint x, uint y)
{
    if(l[x]/S==l[y]/S)return r[x]<r[y];
    return l[x]/S < l[y]/S;
}
void upd(uint x, bool pos, vector<pr> &d)
{
    for(auto T:d)
    {
        uint dlt = pos ? x/T.first : -(x/T.first);
        now += T.second*dlt*((s[T.first]<<1)+dlt);
        s[T.first] += dlt;
    }
}
uint read(uint x=0)
{
    uint c;
    for(c=getchar();!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return x;
}
int main()
{
    uint T, n, q, i, L, R, j;
    init();
    T=read();
    while(T--)
    {
        n=read(), q=read();
        S = sqrt(n);
        rep(i,n)
        {
            a[i]=read();
            d[i].clear();
            for(j=1;j*j<=a[i];j++)
                if(a[i]%j==0)
                {
                    if(mu[j])
                        d[i].emplace_back(pr(j,j*mu[j]));
                    if(j!=a[i]/j and mu[a[i]/j])
                        d[i].emplace_back(pr(a[i]/j,a[i]/j*mu[a[i]/j]));
                    s[j]=s[a[i]/j]=0;
                }
        }
        rep(i,q)
        {
            l[i]=read(), r[i]=read();
            id[i]=i;
        }
        sort(id+1,id+q+1,cmp);
        now = 0;
        L=1, R=0;
        rep(i,q)
        {
            for(;L<l[id[i]];L++)upd(a[L],false,d[L]);
            for(;L>l[id[i]];L--)upd(a[L-1],true,d[L-1]);
            for(;R>r[id[i]];R--)upd(a[R],false,d[R]);
            for(;R<r[id[i]];R++)upd(a[R+1],true,d[R+1]);
            ans[id[i]]=now;
        }
        rep(i,q)
        {
            printf("%u\n",ans[i]);
        }
    }
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值