2301: [HAOI2011]Problem b
Time Limit: 50 Sec Memory Limit: 256 MB
Submit: 2170 Solved: 934
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
Sample Output
14
3
HINT
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
Source
[POI2007]Zap 有一段证明
加上容斥
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define MEM(a) memset(a,0,sizeof(a)); #define MAXN (50000+10) typedef long long ll; int p[MAXN]={0},tot; bool b[MAXN]={0}; int mu[MAXN]={0},sum[MAXN]={0}; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } void make_prime(int n) { tot=0; mu[1]=1; Fork(i,2,n) { if (!b[i]) p[++tot]=i,mu[i]=-1; For(j,tot) { if (i*p[j]>n) break; b[i*p[j]]=1; if (i%p[j]==0) { mu[i*p[j]]=0; break; } mu[i*p[j]]=-mu[i]; } } sum[0]=0; For(i,n) sum[i]=sum[i-1]+mu[i]; } int n,m,d; int calc(int n,int m) { int ans=0; if (n>m) swap(n,m); for(int i=1,last=1;i<=n;i=last+1) { last=min(n/(n/i),m/(m/i)); ans+=(sum[last]-sum[i-1])*(n/i)*(m/i); } return ans; } int main() { // freopen("bzoj2301.in","r",stdin); MEM(p) MEM(b) MEM(mu) MEM(sum) int N = 50000; make_prime(N); int T;T=read(); while(T--) { int a=read(),b=read(),c=read(),d=read(),k=read(); printf("%d\n",calc(b/k,d/k)-calc((a-1)/k,d/k) - calc( b/k, (c-1)/k ) + calc((a-1)/k , (c-1)/k ) ); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-10 06:39:01