• P3312 数表


    P3312 数表

    题意

    求出

    [sum_{i=1}^nsum_{j=1}^msigma(gcd(i,j))[sigma(gcd(i,j))le a] ]

    其中 (sigma) 表示约数和。

    思路/推导

    考虑没有 (a) 的限制的情况。

    [egin{aligned} ans&=sum_{d=1}^{min(n,m)}sigma(d)sum_{i=1}^{leftlfloorfrac{n}{d} ight floor}sum_{j=1}^{leftlfloorfrac{m}{d} ight floor}[gcd(i,j)=1]\ &=sum_{d=1}^{min(n,m)}sigma(d)sum_{i=1}^{leftlfloorfrac{n}{d} ight floor}sum_{j=1}^{leftlfloorfrac{m}{d} ight floor}sum_{pmid iland pmid j}mu(p)\ &=sum_{d=1}^{min(n,m)}sigma(d)sum_{p=1}^{leftlfloorfrac{min(n,m)}{d} ight floor}mu(p)leftlfloorfrac{n}{dp} ight floorleftlfloorfrac{m}{dp} ight floor\ &=sum_{T=1}^{min(n,m)}sum_{d=1}^Tsigma(d)mu(frac Td)leftlfloorfrac{n}{T} ight floorleftlfloorfrac{m}{T} ight floor end{aligned} ]

    考虑加入 (a) 的限制。将询问按照 (a) 大小离线,然后用一个树状数组维护 (sum_dsigma(d)mu(frac Td)) 的前缀和即可。

    具体是将线性筛出的所有数的约数和从小到大进行排序,在从小到大查询的时候进行更新。

    不会筛 (sigma) 的可以看我的另一篇博客

    时间复杂度瓶颈在于查询,需要用到数论分块,为 (O(qsqrt nlog n))

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    #include<utility>
    using namespace std;
    inline int read(){
    	int w=0,x=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=x*10+(c^48),c=getchar();
    	return w?-x:x;
    }
    namespace star
    {
    	const int maxn=1e5+10,maxm=2e4+10,N=1e5;
    	int n,p[maxn/10],mu[maxn],tot,c[maxn],ans[maxm],g[maxn];
    	pair<int,int> f[maxn];
    	bool mark[maxn];
    	inline void insert(int x,int k){for(;x<=N;x+=x&-x) c[x]+=k;}
    	inline int query(int x){int ans=0;for(;x;x-=x&-x) ans+=c[x];return ans;}
    	struct Query{
    		int n,m,a,id;
    		inline bool operator < (const Query& zp) const {return a<zp.a;}
    		inline int solve(){
    			if(n>m) swap(n,m);
    			int ans=0;
    			for(int l=1,r;l<=n;l=r+1)
    				r=min(n/(n/l),m/(m/l)),ans+=((query(r)-query(l-1))*(n/l)*(m/l));
    			return ans;
    		}
    	}q[maxm];
    	inline void work(){
    		mu[1]=1;
    		f[1]=make_pair(1,1);
    		for(int i=2;i<=N;i++){
    			if(!mark[i]) p[++tot]=i,mu[i]=-1,g[i]=i+1,f[i]=make_pair(i+1,i);
    			for(int j=1,tmp;j<=tot and (tmp=i*p[j])<=N;j++){
    				mark[tmp]=true;
    				if(i%p[j]==0){
    					mu[tmp]=0;
    					g[tmp]=g[i]*p[j]+1;
    					f[tmp]=make_pair(f[i].first/g[i]*g[tmp],tmp);
    					break;
    				}
    				mu[tmp]=-mu[i];
    				g[tmp]=p[j]+1;
    				f[tmp]=make_pair(f[i].first*f[p[j]].first,tmp);
    			}
    		}
    		sort(f+1,f+1+N);
    		n=read();
    		for(int i=1;i<=n;i++) q[i].n=read(),q[i].m=read(),q[i].a=read(),q[i].id=i;
    		sort(q+1,q+1+n);
    		for(int i=1,j=1;i<=n;i++){
    			while(f[j].first<=q[i].a and j<=N){
    				for(int k=f[j].second;k<=N;k+=f[j].second) insert(k,f[j].first*mu[k/f[j].second]);
    				j++;
    			}
    			ans[q[i].id]=q[i].solve();
    		}
    		for(int i=1;i<=n;i++) printf("%d
    ",ans[i]&(~(1<<31)));
    	}
    }
    signed main(){
    	star::work();
    	return 0;
    }
    
  • 相关阅读:
    Python元组、列表、字典
    测试通过Word直接发布博文
    Python环境搭建(windows)
    hdu 4003 Find Metal Mineral 树形DP
    poj 1986 Distance Queries LCA
    poj 1470 Closest Common Ancestors LCA
    poj 1330 Nearest Common Ancestors LCA
    hdu 3046 Pleasant sheep and big big wolf 最小割
    poj 3281 Dining 最大流
    zoj 2760 How Many Shortest Path 最大流
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/14360173.html
Copyright © 2020-2023  润新知