【BZOJ1101】Zap(莫比乌斯反演)
题意:多组询问,对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d。
T,a,b,d,x,y<=50000
思路:下底函数分块+积性函数前缀和
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 typedef long long ll; 13 typedef unsigned int uint; 14 typedef unsigned long long ull; 15 typedef pair<int,int> PII; 16 typedef vector<int> VI; 17 #define fi first 18 #define se second 19 #define MP make_pair 20 #define N 110000 21 #define M 410000 22 #define eps 1e-8 23 #define pi acos(-1) 24 #define oo 1e9 25 26 int mu[N+10],s[N+10],prime[N+10],flag[N+10]; 27 28 ll calc(int n,int m) 29 { 30 if(n>m) swap(n,m); 31 ll ans=0; 32 int i=1; 33 while(i<=n) 34 { 35 ll x=n/i; 36 ll y=m/i; 37 int t1=n/x; 38 int t2=m/y; 39 int pos=min(t1,t2); 40 ans+=x*y*(s[pos]-s[i-1]); 41 i=pos+1; 42 } 43 return ans; 44 } 45 46 int main() 47 { 48 int cas; 49 scanf("%d",&cas); 50 mu[1]=1; 51 int m=0; 52 for(int i=2;i<=N;i++) 53 { 54 if(!flag[i]) 55 { 56 prime[++m]=i; 57 mu[i]=-1; 58 } 59 for(int j=1;j<=m;j++) 60 { 61 int t=prime[j]*i; 62 if(t>N) break; 63 flag[t]=1; 64 if(i%prime[j]==0) 65 { 66 mu[t]=0; 67 break; 68 } 69 mu[t]=-mu[i]; 70 } 71 } 72 for(int i=1;i<=N;i++) s[i]=s[i-1]+mu[i]; 73 while(cas--) 74 { 75 int a,b,k; 76 scanf("%d%d%d",&a,&b,&k); 77 a/=k; b/=k; 78 ll ans=calc(a,b); 79 printf("%lld\n",ans); 80 } 81 return 0; 82 }
null