P3312 [SDOI2014]数表

P3312 [SDOI2014]数表

\(\sum_{i=1}^n\sum_{j=1}^m\sigma(gcd(i,j))[\sigma(gcd(i,j)<=a)]\)

\(f(d)=\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=d]\)

\(F(d)=\sum_{i=1}^n\sum_{j=1}^m [|dgcd(i,j)]=\sum_{d|k}f(k)\)

\(f(d)=\sum_{d|k}\mu(\dfrac{k}{d})F(k)=\sum_{d|k}\mu(\left\lfloor\frac{k}{d}\right\rfloor)\left\lfloor\frac{n}{k}\right\rfloor\left\lfloor\frac{m}{k}\right\rfloor\)

\(Ans=\sum_{i=1}^{min(n,m)}\sigma(i)f(i)\)

\(=\sum_{i=1}^{min(n,m)}\sigma(i)\sum_{i|k}\mu(\left\lfloor\frac{k}{i}\right\rfloor)\left\lfloor\frac{n}{k}\right\rfloor\left\lfloor\frac{m}{k}\right\rfloor\)

\(=\sum_{k=1}^{min(n,m)}\left\lfloor\frac{n}{k}\right\rfloor\left\lfloor\frac{m}{k}\right\rfloor\sum_{i|k}\mu(\left\lfloor\frac{k}{i}\right\rfloor)\sigma(i)\)

后半部分预处理筛一遍\(sum_{i|k}\mu(\left\lfloor\frac{k}{i}\right\rfloor)\sigma(i)\),前面分块一下,别忘了还有限制条件\([\sigma(gcd(i,j)<=a)]\),丢到树状数组里就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+9;
inline int Read(){
    int x=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1; c=getchar();
    }
    while(c>='0'&&c<='9')
        x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*f;
}
int mu[maxn],prime[maxn];
bool visit[maxn];
inline void F_phi(int N){
    mu[1]=1; int tot(0);
    for(int i=2;i<=N;++i){
        if(!visit[i]){
            prime[++tot]=i,
            mu[i]=-1;
        }
        for(int j=1;j<=tot&&i*prime[j]<=N;++j){
            visit[i*prime[j]]=true;
            if(i%prime[j]==0)
                break;
            else
                mu[i*prime[j]]=-mu[i];
        }
    }
}
struct _F{
    int id;
    LL val;
}F[maxn];
inline bool cmp_F(_F x,_F y){
    return x.val<y.val;
}

struct Qy{
    int n,m,a,id;
}q[maxn];
inline bool cmp_Q(Qy x,Qy y){
    return x.a<y.a;
}

int sum[maxn];
inline int Lowbit(int i){
    return i&(-i);
}
inline void Add(int i,int val){
    for(;i<=100000;i+=Lowbit(i))
        sum[i]+=val;
}
inline int Query(int i){
    int num(0);
    for(;i;i-=Lowbit(i))
        num+=sum[i];
    return num;
}
inline int Calc(int n,int m){
    int num(0);
    if(n>m)
        swap(n,m);
    for(int l=1,r;l<=n;l=r+1){
        r=min(n/(n/l),(m/(m/l)));
        num+=(n/l)*(m/l)*(Query(r)-Query(l-1));
    }
    return num;
}

int ans[maxn];
int main(){
    F_phi(100000);
    for(int i=1;i<=100000;++i){
        F[i].id=i;
        for(int j=1;j*i<=100000;++j)
            F[j*i].val+=i;
    }
    sort(F+1,F+1+100000,cmp_F);
    
    int T=Read();
    for(int i=1;i<=T;++i){
        int n=Read(),m=Read(),a=Read();
        q[i]=(Qy){n,m,a,i};
    }
    sort(q+1,q+1+T,cmp_Q);
    
    int now(0);
    for(int i=1;i<=T;++i){
        while(now<100000&&F[now+1].val<=q[i].a){
            ++now;
            for(int j=1;j*F[now].id<=100000;++j)
                Add(j*F[now].id,mu[j]*F[now].val);
        }
        ans[q[i].id]=Calc(q[i].n,q[i].m);
    }
    
    for(int i=1;i<=T;++i)
        printf("%d\n",ans[i]&0x7fffffff);
    return 0;
}/*
2
4 4 3
10 10 5

20
148
*/
posted @ 2019-01-06 10:50  y2823774827y  阅读(129)  评论(0编辑  收藏  举报