對於給出的n個詢問,每次求有多少個數對(x,y),知足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函數爲x和y的最大公約數。html
第一行一個整數n,接下來n行每行五個整數,分別表示a、b、c、d、kc++
共n行,每行一個整數表示知足要求的數對(x,y)的個數git
2 2 5 1 5 1 1 5 1 5 2
14 3
100%的數據知足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000函數
前置知識:莫比烏斯反演spa
題目要求的是這個:
\[ ans = \sum _ {i=a}^b \sum _ {j=c}^d [gcd(i,j)=k] \]
咱們能夠利用二位前綴和的思想轉化一下,而後求這個:
\[ ans = \sum _ {i=1}^n \sum _ {j=1}^m [gcd(i,j)=k] \]
把\(k\)除掉:
\[ ans= \sum _ {i=1}^{\lfloor \frac{n}{k} \rfloor} \sum _ {j=1}^{\lfloor \frac{m}{k} \rfloor} [gcd(i,j)=1] \]
而後對於後面的\(gcd\)莫比烏斯反演下,即:
\[ \sum _{d|n} \mu(d) =[ n=1 ] \]
帶進去得:
\[ ans= \sum _ {i=1}^{\lfloor \frac{n}{k} \rfloor} \sum _ {j=1}^{\lfloor \frac{m}{k} \rfloor} \sum _{d|i\&d|j} \mu(d) \]
而後交換下枚舉順序,先枚舉\(d\),得:
\[ \begin {align} ans&= \sum _d\mu(d) \sum _{i=1}^{\lfloor \frac{n}{kd} \rfloor} \sum _{j=1}^{\lfloor \frac{m}{kd} \rfloor} 1 \\ &= \sum _d\mu(d) \lfloor \frac{n}{kd} \rfloor \lfloor \frac{m}{kd} \rfloor \\ \end {align} \]
而後線篩下\(\mu\),整除分塊下,就作完了。code
這裏最好是把\(n\)和\(m\)分別除以\(k\)後在整除分塊,不然親測會慢一倍,雖然\(bzoj\)心情好的話卡時限能過。。htm
#include<bits/stdc++.h> using namespace std; #define int long long void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } void print(int x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} const int maxn = 5e4+10; int mu[maxn],pri[maxn],vis[maxn],tot,T; void sieve() { mu[1]=1; for(int i=2;i<maxn;i++) { if(!vis[i]) pri[++tot]=i,mu[i]=-1; for(int j=1;j<=tot&&i*pri[j]<maxn;j++) { vis[i*pri[j]]=1; if(!(i%pri[j])) {mu[i*pri[j]]=0;break;} else mu[i*pri[j]]=-mu[i]; } } for(int i=1;i<maxn;i++) mu[i]=mu[i]+mu[i-1]; } int calc(int n,int m,int k) { int d=1,ans=0;n/=k,m/=k; while(d<=n&&d<=m) { int pre=d;d=min(n/(n/d),m/(m/d)); ans+=(n/d)*(m/d)*(mu[d]-mu[pre-1]); d++; }return ans; } signed main() { sieve();read(T); for(int i=1,a,b,c,d,k;i<=T;i++) { read(a),read(b),read(c),read(d),read(k); write(calc(b,d,k)-calc(b,c-1,k)-calc(a-1,d,k)+calc(a-1,c-1,k)); } return 0; }