生活随笔
收集整理的這篇文章主要介紹了
BZOJ 2301 - Problem b(莫比乌斯反演+容斥)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接 https://cn.vjudge.net/problem/HYSBZ-2301
【題意】
對于給出的 n 個詢問,每次求有多少個數對(x,y)(x,y) ,滿足 a≤x≤b,c≤y≤da≤x≤b,c≤y≤d ,且 gcd(x,y)=k,gcd(x,y)gcd(x,y)=k,gcd(x,y) 函數為 xx 和 yy 的最大公約數。
【思路】
s1=∑x=1b∑y=1d[gcd(x,y)=k]s1=∑x=1b∑y=1d[gcd(x,y)=k] s2=∑x=1a?1∑y=1d[gcd(x,y)=k]s2=∑x=1a?1∑y=1d[gcd(x,y)=k] s3=∑x=1c?1∑y=1b[gcd(x,y)=k]s3=∑x=1c?1∑y=1b[gcd(x,y)=k] s4=∑x=1a?1∑y=1c?1[gcd(x,y)=k]s4=∑x=1a?1∑y=1c?1[gcd(x,y)=k]則答案為
ans=s1?s2?s3+s4ans=s1?s2?s3+s4 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=
50005;
bool vis[maxn];
int prim[maxn];
int mu[maxn];
ll sum[maxn];
int cnt;
void get_mu(
int n){mu[
1]=
1;
for(
int i=
2;i<=n;i++){
if(!vis[i]){prim[++cnt]=i;mu[i]=-
1;}
for(
int j=
1;j<=cnt && prim[j]*i<=n;j++){vis[prim[j]*i]=
1;
if(i%prim[j]==
0)
break;
else mu[i*prim[j]]=-mu[i];}}
for(
int i=
1;i<maxn;++i) sum[i]=sum[i-
1]+mu[i];
}ll solve(
int a,
int b){
if(a>b) swap(a,b);ll ans=
0;
for(
int L=
1,R;L<=a;L=R+
1){R=min(a/(a/L),b/(b/L));ans+=(sum[R]-sum[L-
1])*(a/L)*(b/L);}
return ans;
}
int main(){get_mu(maxn-
1);
int T;
scanf(
"%d",&T);
while(T--){
int a,b,c,d,k;
scanf(
"%d%d%d%d%d",&a,&b,&c,&d,&k);ll s1=solve(b/k,d/k);ll s2=solve((a-
1)/k,d/k);ll s3=solve((c-
1)/k,b/k);ll s4=solve((a-
1)/k,(c-
1)/k);ll ans=s1-s2-s3+s4;
printf(
"%lld\n",ans);}
return 0;
}
轉載于:https://www.cnblogs.com/wafish/p/10465189.html
總結
以上是生活随笔為你收集整理的BZOJ 2301 - Problem b(莫比乌斯反演+容斥)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。