【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 }

猜你喜欢

转载自www.cnblogs.com/myx12345/p/9836553.html
今日推荐