• 洛咕3312 [SDOI2014]数表


    洛咕3312 [SDOI2014]数表


    终于独立写出一道题了。。。真tm开心(还是先写完题解在写的)

    先无视a的限制,设(f[i])表示i的约数之和

    不妨设(n<m)

    (Ans=sum_{i=1}^nsum_{j=1}^mf[gcd(i,j)])

    (Ans=sum_{x=1}^nf[x]sum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j)=x])

    莫比乌斯反演,(Ans=sum_{x=1}^nf[x]sum_{x|y}mu(frac{y}{x})lfloorfrac{n}{y} floorlfloorfrac{m}{y} floor)

    换个方法枚举,枚举(frac{y}{x})

    (Ans=sum_{x=1}^nf[x]sum_{y=1}^{n/x}mu(y)lfloorfrac{n}{xy} floorlfloorfrac{m}{xy} floor)

    先枚举(xy),再枚举(x)

    (Ans=sum_{x=1}^nlfloorfrac{n}{x} floorlfloorfrac{m}{x} floorsum_{y|x}^nf[y]mu(frac{x}{y}))

    前面数论分块,后面预处理

    现在有了a的限制,只要将询问按照a排序,树状数组维护前缀和,每次加入即可

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
    	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;
    }
    struct naive{unsigned int f,i;}s[100010];
    il bool operator<(const naive&a,const naive&b){return a.f<b.f;}
    struct ques{int n,m,a,i;}Q[100010];
    il bool operator<(const ques&a,const ques&b){return a.a<b.a;}
    unsigned int pri[100010],pr,mu[100010],f[100010],ans[100010];
    bool yes[100010];
    unsigned int t[100010];
    il vd update(int x,unsigned int p){while(x<100001)t[x]+=p,x+=x&-x;}
    il unsigned int query(int x){unsigned int ret=0;while(x)ret+=t[x],x-=x&-x;return ret;}
    int main(){
    	mu[1]=1;
    	for(int i=2;i<100001;++i){
    		if(!yes[i])pri[++pr]=i,mu[i]=-1;
    		for(int j=1;j<=pr&&i*pri[j]<100001;++j){
    			yes[i*pri[j]]=1;
    			if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
    			mu[i*pri[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<100001;++i)
    		for(int j=i;j<100001;j+=i)
    			f[j]+=i;
    	for(unsigned int i=1;i<100001;++i)s[i]=(naive){f[i],i};
    	std::sort(s+1,s+100001);
    	int q=gi(),n,m,a;
    	for(int i=1;i<=q;++i)n=gi(),m=gi(),a=gi(),Q[i]=(ques){n,m,a,i};
    	std::sort(Q+1,Q+q+1);
    	int p=1;
    	for(int i=1;i<=q;++i){
    		while(p<100001&&s[p].f<=Q[i].a){
    			for(int j=s[p].i;j<100001;j+=s[p].i)update(j,mu[j/s[p].i]*f[s[p].i]);
    			++p;
    		}
    		n=Q[i].n,m=Q[i].m;if(n>m)std::swap(n,m);
    		for(int l=1,r;l<=n;++l){
    			r=std::min(n/(n/l),m/(m/l));
    			ans[Q[i].i]+=(query(r)-query(l-1))*(n/l)*(m/l);
    			l=r;
    		}
    	}
    	for(int i=1;i<=q;++i)printf("%u
    ",ans[i]&2147483647);
    	return 0;
    }
    
  • 相关阅读:
    UEditor用法
    String,StringBuffer与StringBuilder差异??
    TsFltMgr.sys其原因是,该系统蓝屏QQ计算机管理器!
    Linux编程实现守护进程
    开机黑屏 只显示鼠标 电脑黑屏 有只老鼠 举 [我们已经成功地解决了]
    页面背景图像的代码
    动态规划01背包问题
    关键部分CCriticalSection使用
    编程:获取股票实时行情数据大全
    iphone开发教程下载
  • 原文地址:https://www.cnblogs.com/xzz_233/p/10087525.html
Copyright © 2020-2023  润新知