hdu 1695(莫比乌斯反演)

此则莫比乌斯反演之大观也,前人之述备矣。

详细的题解 点这里,大佬讲的很详细

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695

 

题意:给定两个区间 [a,b]  ,   [c,d]  一个整数k,x在第一个区间,y在第二个区间;

求有多少个不同的x,y 满足gcd(x,y)==k?,a=c=1;

思路:同时除以k ,问题就转为:[1,b/k] ,[1,d/k] 向下取整,这个区间内的数gcd(x,y)==1的个数;

听大佬说得用容斥 or 莫比乌斯反演(mobius)

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

假设 F(n) 代表gcd(x,y)为n的倍数的数对有多少? f(n) 代表gcd(x,y)为n的数对有多少对?

对于F(n) 我们很容易求得F(n)=floor(上限/n)*floor(上限/n);也很容易得到 $F(n)=\sum_{d|n}{f(d)}$

因为满足上面式子,所以可以根据莫比乌斯反演得到:

$f(n)=\sum_{d|n}{u(d)*\left(\frac{n}{d} \right)}$

我们需要得到f(1)

根据反演定理f(1)=mu[1]*F(1)+mu[2]*F(2)......;很显然上限就是上限中的最小值;

mu[i]就是u(i),

在上面的公式中有一个函数,它的定义如下:

    (1)若,那么

    (2)若均为互异素数,那么

     (3)其它情况下

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cctype>
 4 #include <cmath>
 5 #include <set>
 6 #include <map>
 7 #include <list>
 8 #include <queue>
 9 #include <deque>
10 #include <stack>
11 #include <string>
12 #include <vector>
13 #include <iostream>
14 #include <algorithm>
15 #include <stdlib.h>
16 #include <time.h>
17 using namespace std;
18 typedef long long LL;
19 const int INF=2e9+1e8;
20 
21 const int MOD=1e9+7;
22 const double eps=0.0000000001;
23 void fre()
24 {
25     freopen("test.in","r",stdin);
26     freopen("test.out","w",stdout);
27 }
28 #define MSET(a,b) memset(a,b,sizeof(a))
29 
30 const int maxn=1e5+100;
31 int mu[maxn],vis[maxn];
32 void mobius()
33 {
34     for(int i=1;i<maxn;i++)
35     {
36         int delta=(i==1)-mu[i];
37         mu[i]=delta;
38         for(int j=2*i;j<maxn;j+=i)
39             mu[j]+=delta;
40     }
41 }
42 /**
43  * 我们设:F(n)代表gcd(x,y)是n的倍数的对数;
44  * 设 f(n)代表gcd(x,y)==n 的对数;
45  * F(n)=floor(上限/n)*(上限/n);
46  * 根据莫比乌斯反演
47  */
48 
49 int main()
50 {
51     int ncase,cas=1;
52     scanf("%d",&ncase);
53     mobius();
54     while(ncase--)
55     {
56         int a,b,c,d,k;
57         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
58         printf("Case %d: ",cas++);
59         if(k==0)
60         {
61             printf("0\n");
62             continue;
63         }
64         int x=b/k,y=d/k;
65         if(x>y) swap(x,y);
66         
67         
68         LL ans1=0,ans2=0;
69         for(int i=1;i<=x;i++) ans1+=(LL)mu[i]*(x/i)*(y/i);
70         for(int i=1;i<=x;i++) ans2+=(LL)mu[i]*(x/i)*(x/i);
71         printf("%lld\n",ans1-ans2/2);
72     }
73     return 0;
74 }
75 
76 
77 /**************************************************/
78 /**             Copyright Notice                 **/
79 /**  writer: wurong                              **/
80 /**  school: nyist                               **/
81 /**  blog  : http://blog.csdn.net/wr_technology  **/
82 /**************************************************/

 

 

f(i)=bf(ai)=bbf(aai)=bbf(i)l times b

posted @ 2017-07-28 11:46  Code-dream  阅读(192)  评论(0编辑  收藏  举报