BZOJ 2301[HAOI2011]Problem b
2301: [HAOI2011]Problem b
Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 5072 Solved: 2359
[Submit][Status][Discuss]
Description
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
Input
第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k
Output
共n行,每行一个整数表示满足要求的数对(x,y)的个数
Sample Input
2
2 5 1 5 1
1 5 1 5 2
2 5 1 5 1
1 5 1 5 2
Sample Output
14
3
3
HINT
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
之后同BZOJ 2818
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define LL long long 5 const int maxn=50000; 6 int mu[maxn+10],prime[maxn+10]; 7 int s[maxn+10]; 8 bool book[maxn+10]; 9 int T,a,b,c,d,k,cnt; 10 void ss() 11 { 12 mu[1]=1; 13 for(int i=2;i<=maxn;i++) 14 { 15 if(!book[i]) 16 { 17 prime[++cnt]=i; 18 mu[i]=-1; 19 } 20 for(int j=1;j<=cnt&&i*prime[j]<=maxn;j++) 21 { 22 book[i*prime[j]]=true; 23 if(i%prime[j]) 24 mu[i*prime[j]]=-mu[i]; 25 else 26 { 27 mu[i*prime[j]]=0; 28 break; 29 } 30 } 31 } 32 for(int i=1;i<=maxn;i++) 33 s[i]=s[i-1]+mu[i]; 34 } 35 LL caculate(int n,int m) 36 { 37 if(n>m) 38 swap(n,m); 39 int ans=0,last; 40 for(int i=1;i<=n;i=last+1) 41 { 42 last=min(n/(n/i),m/(m/i)); 43 ans+=(s[last]-s[i-1])*(n/i)*(m/i); 44 } 45 return ans; 46 } 47 int main() 48 { 49 ss(); 50 scanf("%d",&T); 51 while(T--) 52 { 53 scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); 54 --a,--c; 55 a/=k,b/=k,c/=k,d/=k; 56 printf("%d\n",caculate(b,d)-caculate(a,d)-caculate(b,c)+caculate(a,c)); 57 } 58 }