bzoj2301 [HAOI2011]Problem b
Description
Input
第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k
Output
共n行,每行一个整数表示满足要求的数对(x,y)的个数
Sample Input
2 5 1 5 1
1 5 1 5 2
Sample Output
3
HINT
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
正解:莫比乌斯函数。
莫比乌斯函数板子题。。我能说我是为了刷题量才做这题的吗。。
易知$Ans=\sum_{i=1}^{b}\sum_{j=1}^{d}[\gcd(i,j)==k]-\sum_{i=1}^{a-1}\sum_{j=1}^{d}[\gcd(i,j)==k]-\sum_{i=1}^{b}\sum_{j=1}^{c-1}[\gcd(i,j)==k]+\sum_{i=1}^{a-1}\sum_{j=1}^{b-1}[\gcd(i,j)==k]$
于是变成最裸的莫比乌斯函数推导。同除以k,然后把$\mu(p)$的枚举提前,各种套路。。
最后是$Ans=\sum_{p=1}^{min(\frac{b}{k},\frac{d}{k})}\mu(p)\left \lfloor \frac{b}{kp} \right \rfloor\left \lfloor \frac{d}{kp} \right \rfloor-\sum_{p=1}^{min(\frac{a-1}{k},\frac{d}{k})}\mu(p)\left \lfloor \frac{a-1}{kp} \right \rfloor\left \lfloor \frac{d}{kp} \right \rfloor-\sum_{p=1}^{min(\frac{b}{k},\frac{c-1}{k})}\mu(p)\left \lfloor \frac{b}{kp} \right \rfloor\left \lfloor \frac{c-1}{kp} \right \rfloor
\sum_{p=1}^{min(\frac{a-1}{k},\frac{c-1}{k})}\mu(p)\left \lfloor \frac{a-1}{kp} \right \rfloor\left \lfloor \frac{c-1}{kp} \right \rfloor$
然后数论分块,这道题就做完了。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (50010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 int vis[N],mu[N],prime[N],n,m,a,b,c,d,k,cnt,pos; 24 ll ans; 25 26 il int gi(){ 27 RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 28 if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; 29 } 30 31 il void sieve(){ 32 vis[1]=mu[1]=1; 33 for (RG int i=2;i<N;++i){ 34 if (!vis[i]) vis[i]=1,mu[i]=-1,prime[++cnt]=i; 35 for (RG int j=1,k=i*prime[j];j<=cnt && k<N;++j,k=i*prime[j]){ 36 vis[k]=1; if (i%prime[j]) mu[k]=-mu[i]; else break; 37 } 38 } 39 for (RG int i=1;i<N;++i) mu[i]+=mu[i-1]; return; 40 } 41 42 il void work(){ 43 a=gi(),b=gi(),c=gi(),d=gi(),k=gi(); 44 n=b/k,m=d/k,pos=0,ans=0; if (n>m) swap(n,m); 45 for (RG int i=1;i<=n;i=pos+1){ 46 pos=min(n/(n/i),m/(m/i)); 47 ans+=(ll)(mu[pos]-mu[i-1])*(ll)(n/i)*(ll)(m/i); 48 } 49 n=(a-1)/k,m=d/k,pos=0; if (n>m) swap(n,m); 50 for (RG int i=1;i<=n;i=pos+1){ 51 pos=min(n/(n/i),m/(m/i)); 52 ans-=(ll)(mu[pos]-mu[i-1])*(ll)(n/i)*(ll)(m/i); 53 } 54 n=b/k,m=(c-1)/k,pos=0; if (n>m) swap(n,m); 55 for (RG int i=1;i<=n;i=pos+1){ 56 pos=min(n/(n/i),m/(m/i)); 57 ans-=(ll)(mu[pos]-mu[i-1])*(ll)(n/i)*(ll)(m/i); 58 } 59 n=(a-1)/k,m=(c-1)/k,pos=0; if (n>m) swap(n,m); 60 for (RG int i=1;i<=n;i=pos+1){ 61 pos=min(n/(n/i),m/(m/i)); 62 ans+=(ll)(mu[pos]-mu[i-1])*(ll)(n/i)*(ll)(m/i); 63 } 64 printf("%lld\n",ans); return; 65 } 66 67 int main(){ 68 File("b"); 69 sieve(); 70 RG int T=gi(); 71 while (T--) work(); 72 return 0; 73 }