码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3994: [SDOI2015]约数个数和(莫比乌斯反演+分块)

时间:2018-05-30 21:24:32      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:#define   algo   space   zoj   block   define   pre   long   put   

www.cnblogs.com/shaokele/


bzoj3994: [SDOI2015]约数个数和

  Time Limit: 20 Sec
  Memory Limit: 128 MB

Description

  设d(x)为x的约数个数,给定N、M,求 \(\sum_{i=1}^{n}\sum_{j=1}^{m}d(i j)\)
 

Input

  输入文件包含多组测试数据。
  
  第一行,一个整数T,表示测试数据的组数。
  
  接下来的T行,每行两个整数N、M。
 

Output

  T行,每行一个整数,表示你所求的答案。
 

Sample Input

  2
  
  7 4
  
  5 6
 

Sample Output

  110
  
  121
  

题目地址:  bzoj3994: [SDOI2015]约数个数和

题目大意:   题目很简洁了:)

  

题解:

  莫比乌斯反演
  
  初写莫队可以先切这题
  


AC代码

#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
const int N=500005;
int n,m,Q,tot;
int u[N],f[N],g[N],pri[N];
bool fl[N];
inline void init(){
    u[1]=f[1]=1;
    for(int i=2;i<=N;i++){
        if(!fl[i]){
            pri[++tot]=i;
            g[i]=1;
            u[i]=-1;
            f[i]=2;
        }
        for(int j=1;j<=tot && i*pri[j]<=N;j++){
            fl[i*pri[j]]=1;
            if(i%pri[j]==0){
                g[i*pri[j]]=g[i]+1;
                u[i*pri[j]]=0;
                f[i*pri[j]]=f[i]/(g[i]+1)*(g[i]+2);
            }else{
                g[i*pri[j]]=1;
                u[i*pri[j]]=-u[i];
                f[i*pri[j]]=f[i]*2;
            }
        }
    }
    for(int i=2;i<=N;i++)
        f[i]+=f[i-1],u[i]+=u[i-1];
}
int main(){
    init();
    scanf("%d",&Q);
    while(Q--){
        scanf("%d%d",&n,&m);
        if(n>m)swap(n,m);
        ll ans=0;
        int l,r;
        for(l=1;l<=n;l=r+1){
            r=min(n/(n/l),m/(m/l));
            ans+=(ll)(u[r]-u[l-1])*f[n/l]*f[m/l];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

bzoj3994: [SDOI2015]约数个数和(莫比乌斯反演+分块)

标签:#define   algo   space   zoj   block   define   pre   long   put   

原文地址:https://www.cnblogs.com/shaokele/p/9112898.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!