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)=b⋯bf(i)l times b