[SDOI2014]数表

题目链接

题意很明确。

题目不是很难,先讲讲正解,再分享一下我的一些想法(下面默认(n<m))

首先记(sigma(x))(x)因数和

我们先不考虑a的影响,则题目所求的式子为

[sum^{n}_{x=1}{sum^{m}_{y=1} {sigma(gcd(i,j)) }} ]

显然我们枚举gcd

[sum^{n}_{d=1}sum^{n}_{x=1}{sum^{m}_{y=1} {sigma(d)[gcd(i,j)==d] }} ]

[sum^{n}_{d=1}sigma(d)sum^{lfloor frac{n} {d} floor}_{x=1}{sum^{lfloor frac{m} {d} floor}_{y=1} {[gcd(i,j)==1] }} ]

[sum^{n}_{d=1}sigma(d)sum^{lfloor frac{n} {d} floor}_{x=1}{sum^{lfloor frac{m} {d} floor}_{y=1} {sum_{t|gcd(i,j)}mu(t) }} ]

[sum^{n}_{d=1}sigma(d) {sum^{lfloor frac{n} {d} floor}_{t=1}mu(t)sum^{lfloor frac{n} {td} floor}_{x=1}{sum^{lfloor frac{m} {td} floor}_{y=1}1}} ]

[sum^{n}_{d=1}sigma(d) {sum^{lfloor frac{n} {d} floor}_{t=1}mu(t)lfloor frac{n} {td} floorlfloor frac{m} {td} floor} ]

(s)=(t*d)

[sum^{n}_{s=1}lfloor frac{n} {s} floorlfloor frac{m} {s} floor {sum_{d|s}sigma(d)mu(frac{s}{d})} ]

前面的可以整除分块,那后面呢?

我们设(f(s)={sum_{d|s}sigma(d)mu(frac{s}{d})})

然后只要求出(f)的前缀和就(ok)

别忘了还有一个a呢

欸,好像只要(sigma(gcd(i,j)))(leq)(a)就准保没事

(d=gcd(i,j))

也就是说(sigma(d))(leq)(a)才会给(f(s))做贡献

我们随便就可以求出(sigma(d))(n)项的值 (O)((n)) (O(n*log n))随便跑

然后我们离线做,将输入的按(a)升序排列,(sigma(x))也升序排列

然后对于所有的(sigma(d)leq a)的我梦将他扩倍,换言之就是找所有的(d|s)中的(s)(sigma(d)mu(frac{s}{d})) 加到(s)这个地方

单点插入,求前缀和,使用树状数组维护就行了

正解讲完了!!


谈谈我的一些其他想法

我最开始第一步都不是不是这么做的,显然死在半路上了

然后看自己第一步和最后一步都与大多题解都不一样时,我是自闭的

但其实是一样的。。

我的做法,也先不考虑(a)

[sum ^{n}_{i=1}sum ^{m}_{j=1}sum^{n}_{t=1}[t|i]\,[t|j] imes t ]

[sum ^{n}_{t=1}tsum ^{lfloor frac{n}{t} floor}_{i=1}sum^{lfloor frac{m}{t} floor}_{j=1}1 ]

[sum ^{n}_{t=1}tlfloor frac{n}{t} floorlfloor frac{m}{t} floor ]

写到这看到题解我就懵了,因为得出结论

[t={sum_{d|s}sigma(d)mu(frac{s}{d})} ]

当时我以为我推错了 但他是对的!!

为啥呢?

首先大家都知道迪利克雷卷积

几个常见的结论

[varphi * 1 = id ]

[mu * id = varphi ]

[mu * 1 =varepsilon ]

[id *1 = sigma ]

同时他也有交换律,结合律
(mu*id*1=varphi *1)

((mu*1)*id=varphi*1)

(varepsilon*id=id)

显然单位元乘(id)肯定等于(id),最后结论显然成立

所以我的和正解的式子是相同的

(没发现还是我太菜)

最后上代码了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+10,M=1e5,mod=1ll<<31ll;
ll mu[N],pr[N],p[N],tot,t[N],T,ans[N],n,m,a;
struct node{ll n,m,a,id;}h[N];
pair<ll,ll> s[N];
inline int cmp(node a,node c){return a.a<c.a;}
template<class T>void read(T &x){
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9') {f|=(ch=='-');ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
}
inline void insert(ll x,ll v)
{
    for(int i=x;i<=M;i+=(i)&(-i)) t[i]+=v;
}
inline ll query(ll x)
{
    ll k=0;
    for(int i=x;i>0;i-=(i)&(-i)) k+=t[i];
    return k%mod;
}
int main()
{
    mu[1]=1;
    for(int i=2;i<=M;i++)
    {
        if(!pr[i]) p[++tot]=i,mu[i]=-1;
        for(int j=1;p[j]*i<=M&&j<=tot;j++)
        {
            pr[i*p[j]]=1;
            if(i%p[j]==0) break;
            mu[i*p[j]]=-mu[i];
        }
    }
    for(int i=1;i<=M;i++)
    {
        s[i].second=i;
        for(register int d=1;d<=M/i;d++)
            s[i*d].first+=d;
    }
    read(T);
    for(register int i=1;i<=T;i++) read(h[i].n),read(h[i].m),read(h[i].a),h[i].id=i;
    sort(s+1,s+1+M);
    sort(h+1,h+1+T,cmp);
    for(int i=1,j=1;i<=T;i++)
    {
        n=h[i].n,m=h[i].m,a=h[i].a;
        while(s[j].first<=a&&j<=M)
        {
            for(ll d=1;d*s[j].second<=M;d++)
                insert(d*s[j].second,s[j].first*mu[d]);
            j++;
        }
        
        if(n>m) swap(n,m);
        for(int l=1,r=1;l<=n;l=r+1)
        {
            r=min(n/(n/l),m/(m/l));
            ans[h[i].id]+=(n/l)*(m/l)*(query(r)-query(l-1));
        }
        ans[h[i].id]%=mod;
    }
    for(int i=1;i<=T;i++) printf("%lld
",ans[i]);
}
原文地址:https://www.cnblogs.com/Phoenix41/p/12274669.html