[SDOI2014]数表

SDOI2014 数表
题意:已知

[F(n) = sum_{d|n}{d} ]

[sum_{i=1}^{n}sum_{j=1}^{m}{F(gcd(i,j))} mod 2^{31}, F(n) leq a ]

做法:
感谢 acfunction 大佬的题解 给我这个蒟蒻提供思路。
我这只数学辣鸡居然写数学题解。
先忽略 $ a $。

[G(k) = sum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j) == k] ]

[G(k) = sum_{d=1}^{lfloorfrac{n}{k} floor}{mu(d)lfloorfrac{n}{id} floorlfloorfrac{m}{id} floor} ]

[t = id ]

[sum_{i=1}^{n}{F(i)G(i)} ]

[= sum_{i=1}^{n}{F(i)}sum_{i|t}{mu(frac{t}{i})lfloorfrac{n}{t} floorlfloorfrac{m}{t} floor} ]

[= sum_{t=1}^{n}lfloorfrac{n}{t} floorlfloorfrac{m}{t} floorsum_{i|t}{F(i)mu(frac{t}{i})} ]

将所有询问离线,按 $ a $ 排序,边询问边加值,用树状数组维护前缀和再莫比乌斯反演即可。

#include<bits/stdc++.h>
using namespace std;
typedef unsigned int ui;
const int N=100010,mod=2147483647;
int T;
struct P {
	int n,m,a,id;
	friend bool operator<(P xx,P yy) { return xx.a<yy.a; }
};P q[N];
struct W {
	int x,id;
	friend bool operator<(W xx,W yy) { return xx.x<yy.x; }
};W w[N];

int f[N],mu[N],pri[N],lp=0,tr[N],ans[N];
bool p[N];

inline int Min(const int x,const int y) { return x<y? x:y; }
void add(int x,ui w) { for(;x<=N-10;x+=(x&-x)) tr[x]+=w; }
ui ask(int x) { ui sum=0; for(;x;x-=(x&-x)) sum+=tr[x]; return sum; }
void init() {
	for(int i=1;i<=N-10;i++) for(int j=i;j<=N-10;j+=i) f[j]+=(ui)i;
	mu[1]=1;
	for(int i=2;i<=N-10;i++) {
		if(!p[i]) pri[++lp]=i,mu[i]=-1;
		for(int j=1;pri[j]*i<=N-10;j++) {
			p[pri[j]*i]=1; if(i%pri[j]==0) { mu[pri[j]*i]=0;break; }
			mu[pri[j]*i]=-mu[i];
		}
	}
}
ui calc(int n,int m) {
	ui sum=0; if(n>m) swap(n,m);
	for(int l=1,r;l<=n;l=r+1) {
		r=Min(n/(n/l),m/(m/l));
		sum=sum+(n/l)*(m/l)*(ask(r)-ask(l-1));
	}
	return sum;
}
int main() {
	init(),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].id=i;
	for(int i=1;i<=N-10;i++) w[i].x=f[i],w[i].id=i;
	sort(q+1,q+T+1),sort(w+1,w+N-10+1);
	for(int i=1,j=0;i<=T;i++) {
		while(j<N-10&&w[j+1].x<=q[i].a) {
			++j;
			for(int k=1;k*w[j].id<=N-10;k++)
				add(k*w[j].id,w[j].x*mu[k]);
		}
		ans[q[i].id]=calc(q[i].n,q[i].m);
	}
	for(int i=1;i<=T;i++) printf("%d
",ans[i]&mod);
	return 0;
}
原文地址:https://www.cnblogs.com/daniel14311531/p/10274076.html