POI2007 ZAP-Queries(莫比乌斯反演)

POI2007 ZAP-Queries

Statement

∑ i = 1 a ∑ j = 1 b [ gcd ⁡ ( a , b ) = d ] \sum_{i=1}^a\sum_{j=1}^b[\gcd(a,b)=d] i=1aj=1b[gcd(a,b)=d]

Solution

f ( d ) = ∑ i = 1 N ∑ j = 1 M [ gcd ⁡ ( i , j ) = d ] f(d)=\sum_{i=1}^N\sum_{j=1}^M[\gcd(i,j)=d] f(d)=i=1Nj=1M[gcd(i,j)=d]
g ( d ) = ∑ d ∣ d ′ f ( d ′ ) = ∑ i = 1 N ∑ j = 1 M [ gcd ⁡ ( i , j ) ∣ d ] = ∑ i = 1 N ∑ j = 1 M [ i ∣ d ] [ j ∣ d ] = ∑ i = 1 N [ i ∣ d ] ∑ j = 1 M [ j ∣ d ] = ∑ i = 1 N [ i ∣ d ] ⌊ M d ⌋ = ⌊ N d ⌋ ⌊ M d ⌋ \begin{aligned}g(d)&=\sum_{d|d'}f(d')\\ &=\sum_{i=1}^N\sum_{j=1}^M[\gcd(i,j)|d]\\ &=\sum_{i=1}^N\sum_{j=1}^M[i|d][j|d]\\ &=\sum_{i=1}^N[i|d]\sum_{j=1}^M[j|d]\\ &=\sum_{i=1}^N[i|d]\lfloor\frac{M}{d}\rfloor\\ &=\lfloor\frac{N}{d}\rfloor\lfloor\frac{M}{d}\rfloor \end{aligned} g(d)=ddf(d)=i=1Nj=1M[gcd(i,j)d]=i=1Nj=1M[id][jd]=i=1N[id]j=1M[jd]=i=1N[id]dM=dNdM
于是 f ( d ) = ∑ d ∣ d ′ μ ( d ′ d ) g ( d ′ ) f(d)=\sum_{d|d'}\mu(\frac{d'}{d})g(d') f(d)=ddμ(dd)g(d).

A n s = f ( d ) = ∑ d ∣ d ′ μ ( d ′ d ) ⌊ N d ′ ⌋ ⌊ M d ′ ⌋ = ∑ t = 1 min ⁡ { N d , M d } μ ( t ) ⌊ N t d ⌋ ⌊ M t d ⌋ Ans=f(d)=\sum_{d|d'}\mu(\frac{d'}{d})\lfloor\frac{N}{d'}\rfloor\lfloor\frac{M}{d'}\rfloor=\sum_{t=1}^{\min\{\frac{N}{d},\frac{M}{d}\}}\mu(t)\lfloor\frac{N}{td}\rfloor\lfloor\frac{M}{td}\rfloor Ans=f(d)=ddμ(dd)dNdM=t=1min{dN,dM}μ(t)tdNtdM.

  • 由引理: ∀ a , b , c ∈ Z , ⌊ a b c ⌋ = ⌊ ⌊ a b ⌋ c ⌋ \forall a,b,c\in Z,\lfloor\frac{a}{bc}\rfloor=\lfloor\frac{\lfloor\frac{a}{b}\rfloor}{c}\rfloor a,b,cZ,bca=cba.

Code

# define Fast_IO std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
# include "unordered_map"
# include "algorithm"
# include "iostream"
# include "cstdlib"
# include "cstring"
# include "cstdio"
# include "vector"
# include "bitset"
# include "queue"
# include "cmath"
# include "ctime"
# include "map"
# include "set"
# define ll long long
# define ld long double
# define rep1(i,a,b) for(ll i=(a);i<=(b);i++)
# define rep2(i,a,b) for(ll i=(b);i>=(a);i--)
# define pii pair<int,int>
# define pll pair<ll,ll>
# define ph push_back
# define pb pop_back
# define eb emplace_back
# define vi vector<int>
# define vll vector<ll>
# define vpi vector<pii >
# define vpll vector<pll >
# define ri(x) scanf("%d",&x)
# define rf(x) scanf("%f",&x)
# define rl(x) scanf("%lld",&x)
# define rd(x) scanf("%lf",&x)
# define rs(s) scanf("%s",s+1)
# define wi(x) printf("%d",x)
# define wl(x) printf("%lld",x)
# define ws(s) printf("%s",s+1)
# define resize(v,x) v.resize(x)
# define all(v) v.begin(),v.end()
# define reverse(v) reverse(all(v))
# define fi first
# define se second
# define lowbit(x) ((x)&(-(x)))
# define repauto(Name,v) for(auto Name:v)
# define Endl "\n"
using namespace std;
template<class I> inline I GCD(I A,I B){return B?GCD(B,A%B):A;}
template<class I> inline I LCM(I A,I B){return A/GCD(A,B)*B;}
template<class I> I Sqrt(I N){
	I sqrtN=sqrt(N)-1;
	while(sqrtN+1<=N/(sqrtN+1))sqrtN++;
	return sqrtN;
}
template<class I> I Pow(I X,I Y,__int128 Mod1=998244353){
	static __int128 Ans; Ans=1;
	for(;Y;Y>>=1,X=(__int128)X*X%Mod1) if(Y&1) Ans=Ans*X%Mod1;
	return Ans;
}

namespace Mu_Class{
	int Prime_Cnt;
	int *Prime=new int;
	int *Mu=new int;
	int *Visit=new int;
	inline void Init(int N){
		static int i,j;
		delete Visit;	Visit=new int[N+1]();
		delete Prime;	Prime=new int[N+1]();
		delete Mu;		Mu=new int[N+1]();
		for(Mu[1]=1,i=2;i<=N;i++){
			if(!Visit[i]){
				Visit[i]=i,Mu[i]=-1;
				Prime[++Prime_Cnt]=i;
			}for(j=1;j<=Prime_Cnt && Visit[i]>=Prime[j] && Prime[j]<=N/i;j++){
				Mu[i*Prime[j]]=Visit[i]==Prime[j]?0:Mu[i]*(-1);
				Visit[i*Prime[j]]=Prime[j];
			}
		}for(i=1;i<=N;i++) Mu[i]+=Mu[i-1];
		return;
	}
}using namespace Mu_Class;

int T;
int N,M,D;
long long Ans;

int main(){
# ifdef LH_Frank
    freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);
# endif
	ri(T);
	Init(50000);
	while(T--){
		ri(N),ri(M),ri(D);
		N/=D,M/=D;
		Ans=0;
		for(int i=1;i<=min(N,M);){
			int j=min(N/(N/i),M/(M/i));
			Ans+=1LL*(N/i)*(M/i)*(Mu[j]-Mu[i-1]);
			i=j+1;
		}printf("%lld\n",Ans);
	}
	return 0;
}

Link

[1] Luogu P3455 [POI2007]ZAP-Queries

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值