zoukankan      html  css  js  c++  java
  • BZOJ:3529: [Sdoi2014]数表

    题解:

    反演,按a从小到大排序,依次加入符合题意的f(d)值;

    用树状数组维护前缀和

    注意:

      取模时做差注意负数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long Lint;
    const int maxQ=20009;
    const int maxn=100009;
    const Lint mm=(1LL<<31);
    
    int T;
    Lint ans[maxn];
    struct questions{
    	int n,m,a,idx;
    }q[maxQ];
    int cmp(const questions &tmp1,const questions &tmp2){
    	return tmp1.a<tmp2.a;
    }
    
    Lint f[maxn];
    Lint g[maxn];
    int d[maxn];
    int cmp2(const int &tmp1,const int &tmp2){
    	if(f[tmp1]<f[tmp2])return 1;
    	else return 0;
    }
    
    int vis[maxn]={0};
    int prime[maxn],cntprime;
    int mu[maxn];
    int r[maxn];
    int prepro(){
    	vis[1]=1;mu[1]=1;
    	for(int i=2;i<=100000;++i){
    		if(!vis[i]){
    			prime[++cntprime]=i;
    			mu[i]=-1;
    		}
    		for(int j=1;j<=cntprime&&i*prime[j]<=100000;++j){
    			vis[i*prime[j]]=1;
    			if(i%prime[j]==0){
    				mu[i*prime[j]]=0;
    				break;
    			}
    			mu[i*prime[j]]=-mu[i];
    		}
    	}
    	for(int i=2;i<=100000;++i)mu[i]+=mu[i-1];
    	for(int d=1;d<=100000;++d){
    		for(int k=1;k*d<=100000;++k){
    			f[d*k]=(f[d*k]+d)%mm;
    		}
    	}
    	for(int i=1;i<=100000;++i)r[i]=i;
    	sort(r+1,r+1+100000,cmp2);
    }
    
    Lint c[maxn];	
    inline int lowbit(int x){
    	return x&(-x);
    }
    int add(int x,Lint val){
    	while(x<=100000){
    		c[x]=(c[x]+val)%mm;
    		x+=lowbit(x);
    	}
    }
    Lint query(int x){
    	Lint ret=0;
    	while(x){
    		ret=(ret+c[x])%mm;
    		x-=lowbit(x);
    	}
    	return ret;
    }
    
    int minit(){
    	memset(f,0,sizeof(f));
    	memset(g,0,sizeof(g));
    	memset(c,0,sizeof(c));
    	cntprime=0;
    }
    
    int main(){
    	minit();
    	prepro();
    	
    	scanf("%d",&T);
    	for(int i=1;i<=T;++i){
    		scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a);
    		q[i].idx=i;
    	}
    	sort(q+1,q+1+T,cmp);
    	
    	int head=0;
    	for(int i=1;i<=T;++i){
    		while((head<100000)&&(f[r[head+1]]<=q[i].a)){
    			int v=r[++head];
    			for(int k=1;k*v<=100000;++k){
    				add(k*v,f[v]*(mu[k]-mu[k-1]));
    			}
    		}
    		int n=q[i].n;
    		int m=q[i].m;
    		int a=q[i].a;
    		if(n>m)swap(n,m);
    		Lint ret=0;
    		int last;
    		for(int j=1;j<=n;j=last+1){
    			last=min(n/(n/j),m/(m/j));
    			ret=ret+(query(last)-query(j-1)+mm)*1LL*(n/j)*(m/j);
    			ret=ret%mm;
    		}
    		ans[q[i].idx]=ret;
    	}
    	
    	for(int i=1;i<=T;++i){
    		printf("%lld
    ",ans[i]);
    	}
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    浅谈PHP7新特性
    TP5与TP3.X对比
    深入源码理解Spark RDD的数据分区原理
    OpenGL的一些基础概念
    关于Spark RDD 的认识
    Ubuntu安装Cloudera Manager以及CDH5.15.2
    小甲鱼零基础汇编语言学习笔记第六章之包含多个段的程序
    小甲鱼零基础汇编语言学习笔记第五章之[BX]和loop指令
    机器学习入门之决策树算法
    机器学习的基本概念
  • 原文地址:https://www.cnblogs.com/zzyer/p/8179434.html
Copyright © 2011-2022 走看看