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
*/

原文地址:https://www.cnblogs.com/y2823774827y/p/10227373.html

时间: 2024-08-27 15:19:57

P3312 [SDOI2014]数表的相关文章

【每日题解 #12】P3312 [SDOI2014]数表

啊啊啊我昨天怎么没写题解wwww 补昨日题解... 题目链接 : https://www.luogu.org/problemnew/show/P3312 也是莫反 我要把fft留到今天写 [和zyn小可爱约好了 明天不填完坑就请她cafeking哦 表面题意:很明显了... 有一张N*m的数表,其第i行第j列(1 < =i < =n,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和. 给定a,计算数表中不大于a的数之和. 第一步 : 每个格子里的那个东西是什么? 整

[bzoj3529] [洛谷P3312] [Sdoi2014] 数表

Description 有一张n×m的数表,其第i行第j列(1 < =i < =n,1 < =j < =m)的数值为 能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. Input 输入包含多组数据. 输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据. Output 对每组数据,输出一行一个整数,表示答案模2^31的值. Sample Input 2 4 4 3 10 10 5 Samp

BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]

3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status][Discuss] Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. Input 输入包含多组数据.    输入的第一行一个整数Q表示测试点内的数据

【BZOJ3529】[Sdoi2014]数表 莫比乌斯反演+树状数组

[BZOJ3529][Sdoi2014]数表 Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. Input 输入包含多组数据.    输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据. Output 对每组数据,输出一行一个整数,表示答案模2^31的值. Sample I

bzoj [SDOI2014]数表 莫比乌斯反演 BIT

bzoj [SDOI2014]数表 莫比乌斯反演 BIT 链接 bzoj luogu loj 思路 \[ \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}a*[f[gcd(i,j)]<=a] \] \[ f[]可以O(n)预处理出来 \] \[ \sum\limits_{k=1}^{n}f[k]*\sum\limits_{i=1}^{m}\sum\limits_{j=1}^{m}[gcd(i,j)==k] \] \[ \sum\limits_{k=1}^{n}

[bzoj3529][Sdoi2014]数表_树状数组_莫比乌斯反演

数表 bzoj-3529 Sdoi-2014 题目大意:n*m的数表,第i行第j列的数是同时整除i和j的所有自然数之和.给定a,求数表中所有不超过a的和. 注释:$1\le n,m \le 10^5$. 想法:我们先不考虑那个a的限制:我们设f(i)表示整除i的自然数之和. $\sum\limits_{i=1}^n\sum\limits_{j=1}^m f(gcd(i,j))$ $\sum\limits_{i=1}^n\sum\limits_{j=1}^m f(d)\cdot [gcd(i,j)

BZOJ 3529: [Sdoi2014]数表

Description 有一张N×m的数表,其第i行第j列(1 < =i < =n,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. HINT 1 < =N.m < =10^5  , 1 < =Q < =2×10^4 Solution 先假设a的限制不存在 正面把答案强行写出来是这样的 其中F(i)为i的约数和,可以线性筛处理 然后慢慢化简其中的各个部分 令g(i)为1<=x<=n,1<

[BZOJ3529][Sdoi2014]数表

试题描述 有一张N×m的数表,其第i行第j列(1 < =i < =n,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. 输入 输入包含多组数据.输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据. 输出 对每组数据,输出一行一个整数,表示答案模2^31的值. 输入示例 2 4 4 3 10 10 5 输出示例 20 148 数据规模及约定 1 < =

【BZOJ3529】【莫比乌斯反演 + 树状数组】[Sdoi2014]数表

Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为 能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. Input 输入包含多组数据.     输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据. Output 对每组数据,输出一行一个整数,表示答案模2^31的值. Sample Input 2 4 4 3 10 10 5