• BZOJ3529: [Sdoi2014]数表


    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3529

    挺恶心的数论TAT。。。

    设f[i]是i的约数和,这个可以nln(n)扫出来。

    ans=∑d[n/d]*[m/d]*∑i|d f[i]*μ[d/i]

    然后由于只有f[i]<=a是有用的,所以对给的a从小到大排序,对求的f[i]从小到大排序,用个树状数组维护一下。

    由于分块思想,可以枚举d,然后会出现一段n/i是一样的,所以把那部分区间求和就可以了。

    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define inf 1000000009
    #define ll long long
    #define maxn 100500
    #define mm 2147483648
    #define low(x) (x&(-x))
    using namespace std;
    struct data{int a,n,m,b,id;
    }a[maxn];
    struct node{int a;int b;
    }f[maxn];
    int tot,mx,T,b[maxn],pri[maxn],mu[maxn],ans[maxn];
    int t[maxn];
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)){if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    bool cmpa(data a,data b){
        return a.a<b.a;
    }
    bool cmp(node a,node b){
        return a.a<b.a;
    }
    void pre(){
        mu[1]=1;
        rep(i,2,mx){
            if (!b[i]) b[i]=1,pri[++tot]=i,mu[i]=-1;
            rep(j,1,tot)if (i*pri[j]<=mx){
                b[i*pri[j]]=1; 
                if (i%pri[j]==0) {mu[i*pri[j]]=0; break;}
                else mu[i*pri[j]]=-mu[i];
            }
            else break;
        }
        rep(i,1,mx) 
            for (int j=i;j<=mx;j+=i) f[j].a+=i;
        rep(i,1,mx) f[i].b=i;
    }
    void add(int x,int y){
        while (x<=mx){
            t[x]+=y; x+=low(x);
        }
    }
    int ask(int x){
        int ans=0;
        while (x){
            ans+=t[x];
            x-=low(x);
        }
        return ans;
    }
    void solve(int id){
        int n=a[id].n,m=a[id].m;
        for (int i=1,j;i<=n;i=j+1){
            j=min(n/(n/i),m/(m/i));
            ans[a[id].id]+=(n/i)*(m/i)*(ask(j)-ask(i-1));
        }    
    }
    int main(){
        int q=read();
        rep(i,1,q){
            a[i].n=read(); a[i].m=read(); a[i].a=read(); a[i].id=i;
            if (a[i].n>a[i].m) swap(a[i].n,a[i].m);
            mx=max(mx,a[i].n);
        }
        pre();
        sort(a+1,a+1+q,cmpa);
        sort(f+1,f+1+mx,cmp);
        int now=1;
        rep(i,1,q){
            while (f[now].a<=a[i].a&&now<=mx){
                for (int j=f[now].b;j<=mx;j+=f[now].b){
                    add(j,f[now].a*mu[j/f[now].b]);
                }
                now++;
            }
            solve(i);
        }    
        rep(i,1,q) printf("%d
    ",ans[i]&0x7fffffff);
        return 0;
    }
  • 相关阅读:
    网站访问量大 怎样优化mysql数据库
    BootStrap 模态框禁用空白处点击关闭
    常用SQL语句
    诅咒JavaScript之----ArcGIS JavaScript 点聚合 ClusterLayer
    模态框与 天地图地图控件冲突
    FXK Javascript
    从列表中或数组中随机抽取固定数量的元素组成新的数组或列表
    wangEditor
    手把手教你用vue-cli构建一个简单的路由应用
    解决eclipse端口被占用的问题
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5149725.html
Copyright © 2020-2023  润新知