zoukankan      html  css  js  c++  java
  • BZOJ3994: [SDOI2015]约数个数和

    Description

     设d(x)为x的约数个数,给定N、M,求  
     

     

    Input

    输入文件包含多组测试数据。

    第一行,一个整数T,表示测试数据的组数。
    接下来的T行,每行两个整数N、M。
     

    Output

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

     

    Sample Input

    2
    7 4
    5 6

    Sample Output

    110
    121

    HINT

    1<=N, M<=50000

    1<=T<=50000
     
    这篇blog讲得很不错http://blog.codebursts.com/bzoj3994/
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=50010;
    int mu[maxn],f[maxn],vis[maxn],pri[maxn],cnt;
    ll d[maxn];
    void gen(int n) {
        mu[1]=1;d[1]=1;
        rep(i,2,n) {
            if(!vis[i]) pri[++cnt]=i,mu[i]=-1,d[i]=2,f[i]=1;
            rep(j,1,cnt) {
                if(i*pri[j]>n) break;
                vis[i*pri[j]]=1;
                if(i%pri[j]==0) {
                    mu[i*pri[j]]=0;
                    f[i*pri[j]]=f[i]+1;
                    d[i*pri[j]]=d[i]/(f[i]+1)*(f[i]+2);
                    break;
                }
                mu[i*pri[j]]=-mu[i];
                d[i*pri[j]]=d[i]*d[pri[j]];
                f[i*pri[j]]=1;
            }
        }
        rep(i,2,n) d[i]+=d[i-1],mu[i]+=mu[i-1];
    }
    ll solve(int n,int m) {
        if(n>m) swap(n,m);ll ans=0;
        rep(i,1,n) {
            int last=min(n/(n/i),m/(m/i));
            ans+=(mu[last]-mu[i-1])*d[n/i]*d[m/i];
            i=last;
        }
        return ans;
    }
    int main() {
        gen(50000);
        dwn(T,read(),1) printf("%lld
    ",solve(read(),read()));
        return 0;
    }
    View Code
  • 相关阅读:
    ros 录制
    shell 截取字符串
    Linux 关机
    shell获取字符串长度
    ubuntu14.04 设置开机自启动脚本
    获取本机ip的shell脚本
    shell 杀掉指定进程的服务
    html 绘制矩形轨迹,选中区域
    shell模拟ctrl c停止
    shell 字符串提取数字
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5242464.html
Copyright © 2011-2022 走看看