# BZOJ 2301: [HAOI2011]Problem b（莫比乌斯反演）

http://www.lydsy.com/JudgeOnline/problem.php?id=2301

1 #include<iostream>
2 #include<algorithm>
3 #include<cstring>
4 #include<cstdio>
5 #include<sstream>
6 #include<vector>
7 #include<stack>
8 #include<queue>
9 #include<cmath>
10 #include<map>
11 #include<set>
12 using namespace std;
13 typedef long long ll;
14 typedef pair<int,int> pll;
15 const int INF = 0x3f3f3f3f;
16 const int maxn = 1e5 + 5;
17
18 int a, b, c, d, k;
19
20 bool check[maxn];
21 int prime[maxn];
22 int mu[maxn];
23 int sum[maxn];
24
25 void Moblus()
26 {
27     memset(check, false, sizeof(check));
28     mu[1] = 1;
29     int tot = 0;
30     for (int i = 2; i <= maxn; i++)
31     {
32         if (!check[i])
33         {
34             prime[tot++] = i;
35             mu[i] = -1;
36         }
37         for (int j = 0; j < tot; j++)
38         {
39             if (i * prime[j] > maxn)
40             {
41                 break;
42             }
43             check[i * prime[j]] = true;
44             if (i % prime[j] == 0)
45             {
46                 mu[i * prime[j]] = 0;
47                 break;
48             }
49             else
50             {
51                 mu[i * prime[j]] = -mu[i];
52             }
53         }
54     }
55     return ;
56 }
57
58 int solve(int n, int m)
59 {
60     if(n>m)  swap(n,m);
61     int ans=0;
62
63     for(int i=1,last=0;i<=n;i=last+1)
64     {
65         last=min(n/(n/i),m/(m/i));  //分块处理
66         ans+=(sum[last]-sum[i-1])*(n/i)*(m/i);
67     }
68     return ans;
69 }
70
71
72 int main()
73 {
74     //freopen("in.txt","r",stdin);
75     int T;
76     Moblus();
77     sum[0]=0;
78     for(int i=1;i<=maxn;i++)  sum[i]=sum[i-1]+mu[i];
79
80     scanf("%d",&T);
81     while(T--)
82     {
83         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
84         printf("%d\n",solve(b/k,d/k)-solve(b/k,(c-1)/k)-solve((a-1)/k,d/k)+solve((a-1)/k,(c-1)/k));
85     }
86     return 0;
87 }

posted @ 2017-07-28 15:02  、苏州城外的微笑  阅读(...)  评论(...编辑  收藏