[SDOI2015]约数个数和

 出处:http://www.cnblogs.com/peng-ym/p/8667321.html

 

题目:  链接:https://www.luogu.org/problemnew/show/P3327

 

思路: 首先对于 d(x) 有个 性质  : 

            然后开始推:1.先设  

                                  2.

 

                                 3.

                                 4.  (从 3 到4  用到了 莫比乌斯的一个性质:

 

                                 5. 

                                 6. 

                                 7.

                                 8. 

 

 

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define dep(i,j,k) for(int i=k;i>=j;i--)
#define INF 0x3f3f3f3f
#define mem(i,j) memset(i,j,sizeof(i))
#define make(i,j) make_pair(i,j)
#define pb push_back
using namespace std;
const int N=5e4+5;
int sum[N],pre[N],mu[N],tot;
bool vis[N];
LL tmp[N];
void init() {
    mu[1]=1;
    rep(i,2,N-5) {
        if(!vis[i]) { pre[++tot]=i; mu[i]=-1; }
        for(int j=1;j<=tot&&pre[j]*i<=N-5;j++) {
            vis[i*pre[j]]=1;
            if(i%pre[j]==0) break;
            mu[i*pre[j]]=-mu[i];
        }
    }
    rep(i,1,N-5) sum[i]=sum[i-1]+mu[i];
    rep(i,1,N-5) {
        for(int l=1,r;l<=i;l=r+1) {
            r=i/(i/l);
            tmp[i]+=1LL*(r-l+1)*(i/l);
        }
    }
}
int main() {
    init();
    int t,n,m;
    scanf("%d",&t);
    while(t--) {
        scanf("%d %d",&n,&m);
        LL ans=0;
        for(int l=1,r;l<=min(n,m);l=r+1) {
            r=min(n/(n/l),m/(m/l));
            ans+=(sum[r]-sum[l-1])*1LL*tmp[n/l]*tmp[m/l];
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

posted on 2019-05-24 12:38  Willems  阅读(161)  评论(0编辑  收藏  举报

导航