题目大意:给定两个区间ab与cd问两区间内能有多少组数据组成GCD(x,y)=k;
每行五个整数a,b,c,d,k(1 <= a <= b <= 50000,1 <= c <= d <=50000,1 <= k <= 50000)。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<math.h> #define ll long long #define MAX 1000010 bool vis[1000010]; ll prime[1000010],mu[1000010],su[1000010]; using namespace std; void mobus() { memset(vis,false,sizeof(vis)); mu[1]=1; int s=0; for(int i=2; i<=1000000; i++) { if(!vis[i]) { prime[s++]=i; mu[i]=-1; } for(int j=0; j<s&&prime[j]*i<=1000010; j++) { vis[prime[j]*i ]=true; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } else mu[i*prime[j] ]=-mu[i]; } } } ll so(int n,int m) { ll ans=0; if(n>m) { n^=m; m^=n;n^=m; } for(int i=1,la=0; i<=n; i=la+1) { la=min(n/(n/i),m/(m/i)); ans+=(ll )(su[la]-su[i-1])*(n/i)*(m/i); } return ans; } int main() { ll n,m,i,j,a1,b1,c1,d1,k1,a,b,c,d,k; mobus(); su[0]=0; for(i=1; i<=60000; i++) su[i]=su[i-1]+mu[i]; int cla; scanf("%d",&cla); for(int gr=1; gr<=cla; gr++) { scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k); printf("%lld\n",so(b/k,d/k)-so((a-1)/k,d/k)-so(b/k,(c-1)/k)+so((a-1)/k,(c-1)/k)); } return 0; }