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;
}

  

自己还是太辣鸡了
原文地址:https://www.cnblogs.com/zzyer/p/8179434.html