1. 程式人生 > >[BZOJ 3309]DZY Loves Math 莫比烏斯反演

[BZOJ 3309]DZY Loves Math 莫比烏斯反演

2-2 color 答案 圖片 pan 組合 != clu 固定

還是需要看題解T-T

枚舉d=gcd(i,j),得到

技術分享圖片

好了現在就要處理後邊這個函數了,可以無腦求,不過107顯然會T,當然要O(n)了

然後我們就觀察這個函數。。大力分析一下µ可能會帶來的貢獻

令T=p1a1*p2a2*...*pkak

d=p1b1*p2b2*...*pkbk

若μ(T/d)!=0,那麽T/d後各項次數0<=(ai-bi)<=1

分一下類:

①若ai!=aj

我們知道對於f(d)有貢獻的是最大次項,設為ax

假如固定d包含約數pax,那麽f(d)=ax,T的所有約數d的其他次冪就要選擇了。

根據組合數的性質,選擇奇數和偶數的方案是一樣的,而它對答案f(d)的系數的貢獻分別為±1,這樣一綜合為0

②若所有的a都相等

我們假設對於任意選取方案,f值都不變

那麽由於選取奇數個元素和偶數個元素的方案數相等,和仍然為0

但是有一種選取方案,那就是全部選,它的f值就變為了a-1,因為它的最高次冪不是a了

但是它對應的方案選取的f值還是a,所以一綜合,我們就要處理掉這個差出來的1

考慮到μ的符號之後,最終結果為(-1)(k+1)

最終結果:故所有a都相等,則g(T)=(-1)(k+1)

然後根據lc大神教的O(n)思路去處理就好啦!記得開long long

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define N 10100000
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
#define LL long long
int t,n,m;
int notprime[N],prime[N];
LL g[N],K[N],G[N];
void get_pre(){
	notprime[1]=1;
	pos(i,2,N-10){
		if(!notprime[i]){
			prime[++prime[0]]=i;
			g[i]=1;K[i]=1;G[i]=i;
		}
		for(int j=1;j<=prime[0]&&prime[j]*i<=N-10;j++){
			notprime[i*prime[j]]=1;
			if(i%prime[j]==0){
				K[i*prime[j]]=K[i]+1;
				G[i*prime[j]]=G[i]*prime[j];
				int i1=i*prime[j]/G[i*prime[j]];
				if(i1==1) g[i*prime[j]]=1;
				else{
					if(K[i1]==K[i*prime[j]]) g[i*prime[j]]=-g[i1];
					else g[i*prime[j]]=0;
				}
				break;
			}
			G[i*prime[j]]=prime[j];
			K[i*prime[j]]=1;
			if(K[i]==1) g[i*prime[j]]=-g[i];
			else g[i*prime[j]]=0;
		}
	}
	pos(i,1,N-10) g[i]+=g[i-1];
}
LL get_ans(){
	if(n>m) swap(n,m);
	LL res(0);
	int last(0);
	for(int i=1;i<=n;i=last+1){
		last=min(n/(n/i),m/(m/i));
		res+=(n/i)*1ll*(m/i)*1ll*(g[last]-g[i-1]);
	}
	return res;
}
int main(){
	scanf("%d",&t);
	get_pre();
	while(t--){
		scanf("%d%d",&n,&m);
		printf("%lld\n",get_ans());
	}
	return 0;
}

  

[BZOJ 3309]DZY Loves Math 莫比烏斯反演