【Luogu】 P3312 [SDOI2014]数表

题目描述

点击打开链接

题目解法

我们令 g ( x ) g(x) g(x) x x x 的约数和
答案为:
∑ i = 1 n ∑ j = 1 m [ g [ g c d ( i , j ) ] < = a ] g [ g c d ( i , j ) ] \sum_{i=1}^{n}\sum_{j=1}^{m}[g[gcd(i,j)]<=a]g[gcd(i,j)] i=1nj=1m[g[gcd(i,j)]<=a]g[gcd(i,j)]
按照套路枚举 g c d ( i , j ) gcd(i,j) gcd(i,j)
∑ d = 1 m i n ( n , m ) [ g ( d ) < = a ] ∑ i ′ = 1 ⌊ n d ⌋ ∑ j ′ = 1 ⌊ m d ⌋ [ g c d ( i ′ , j ′ ) = 1 ] g ( d ) \sum_{d=1}^{min(n,m)}[g(d)<=a]\sum_{i'=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum_{j'=1}^{\left \lfloor \frac{m}{d} \right \rfloor}[gcd(i',j')=1]g(d) d=1min(n,m)[g(d)<=a]i=1dnj=1dm[gcd(i,j)=1]g(d)
如果 x > 1 x>1 x>1,那么 ∑ d ∣ x μ ( d ) \sum_{d|x} \mu(d) dxμ(d) 0 0 0
∑ d = 1 m i n ( n , m ) [ g ( d ) < = a ] g [ d ] ∗ ∑ i ′ = 1 ⌊ n d ⌋ ∑ j ′ = 1 ⌊ m d ⌋ ∑ d ′ ∣ i ′ 且 d ′ ∣ j ′ μ ( d ′ ) \sum_{d=1}^{min(n,m)}[g(d)<=a]g[d]*\sum_{i'=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum_{j'=1}^{\left \lfloor \frac{m}{d} \right \rfloor}\sum_{d'|i'且d'|j'}\mu(d') d=1min(n,m)[g(d)<=a]g[d]i=1dnj=1dmdidjμ(d)
交换 i ′ , j ′ , d ′ i',j',d' i,j,d 的循环顺序:
∑ d = 1 m i n ( n , m ) [ g ( d ) < = a ] g [ d ] ∗ ∑ d ′ = 1 m i n ( ⌊ n d ⌋ , ⌊ m d ⌋ ) μ ( d ′ ) ⌊ n d d ′ ⌋ ⌊ m d d ′ ⌋ \sum_{d=1}^{min(n,m)}[g(d)<=a]g[d]*\sum_{d'=1}^{min(\left \lfloor \frac{n}{d} \right \rfloor,\left \lfloor \frac{m}{d} \right \rfloor)}\mu(d')\left \lfloor \frac{n}{dd'} \right \rfloor\left \lfloor \frac{m}{dd'} \right \rfloor d=1min(n,m)[g(d)<=a]g[d]d=1min(dn,dm)μ(d)ddnddm
T = d d ′ T=dd' T=dd,且先枚举 T T T 来交换循环顺序:
∑ T = 1 m i n ( N , M ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ d ∣ T [ g ( d ) < = a ] g ( d ) ∗ μ ( T d ) \sum_{T=1}^{min(N,M)}\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor\sum_{d|T}[g(d)<=a]g(d)*\mu(\frac{T}{d}) T=1min(N,M)TnTmdT[g(d)<=a]g(d)μ(dT)
我么令 h ( T ) h(T) h(T) ∑ d ∣ T [ g ( d ) < = a ] g ( d ) ∗ μ ( T d ) \sum_{d|T}[g(d)<=a]g(d)*\mu(\frac{T}{d}) dT[g(d)<=a]g(d)μ(dT)
我们可以把询问离线下来,按照 a a a 从小到大排序
然后用每个 g ( d ) g(d) g(d) 来更新 h ( T ) h(T) h(T),这样全部更新一遍的复杂度大概是 O ( n l o g n ) O(nlogn) O(nlogn)
每个答案可以用数论分块 O ( n ) O(\sqrt n) O(n ) 求出
这里的 h ( T ) h(T) h(T) 因为需要满足单点修改和区间求和的操作,所以可以用常数较小的树状数组来实现
时间复杂度 O ( n l o g n n ) O(nlogn\sqrt n) O(nlognn )

#include <bits/stdc++.h>
#define lowbit(x) x&-x
#define int long long
using namespace std;
typedef pair<int,int> pii;
const int N(100100),Q(20100);
struct Query{
	int n,m,a,id;
}query[Q];
int g[N],h[N],ANS[Q];
int pr[N],cnt,v[N],mu[N];
pii sortg[N];
inline int read(){
	int FF=0,RR=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
	for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
	return FF*RR;
}
bool cmp(const Query &x,const Query &y){
	return x.a<y.a;
} 
void init(){
	mu[1]=1;
	for(int i=2;i<N;i++){
		if(!v[i]) v[i]=pr[++cnt]=i,mu[i]=-1;
		for(int j=1;i<=(N-1)/pr[j];j++){
			v[pr[j]*i]=pr[j];
			if(v[i]==pr[j]) break;
			mu[pr[j]*i]=-mu[i];
		}
	}
	for(int i=1;i<N;i++)
		for(int j=i;j<N;j+=i)
			g[j]+=i;
	for(int i=1;i<N;i++)
		sortg[i]=make_pair(g[i],i);
	sort(sortg+1,sortg+N);
}
void add(int x,int c){
	for(;x<N;x+=lowbit(x))
		h[x]+=c;
}
int ask(int x){
	int res=0;
	for(;x;x-=lowbit(x))
		res+=h[x];
	return res;
}
int get_next(int n,int k){
	return n/(n/k);
}
signed main(){
	init();
	int q=read();
	for(int i=1;i<=q;i++)
		query[i].n=read(),query[i].m=read(),query[i].a=read(),query[i].id=i;
	sort(query+1,query+q+1,cmp);
	int p=1;
	for(int i=1;i<=q;i++){
		while(p<N&&sortg[p].first<=query[i].a){
			int d=sortg[p].second;
			for(int j=d;j<N;j+=d)
				add(j,mu[j/d]*g[d]);
			p++;
		}
		int Newn=min(query[i].n,query[i].m);
		int ans=0;
		for(int l=1;l<=Newn;){
			int r=min(Newn,min(get_next(query[i].n,l),get_next(query[i].m,l)));
			ans+=(ask(r)-ask(l-1))*(query[i].n/l)*(query[i].m/l);
			l=r+1;
		}
		ANS[query[i].id]=ans;
	}
	for(int i=1;i<=q;i++)
		printf("%lld\n",ANS[i]%(1ll<<31));
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值