码迷,mamicode.com
首页 > 其他好文 > 详细

hdu1695 GCD(莫比乌斯入门题)

时间:2016-11-04 01:07:56      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:复杂   sub   入门   print   image   log   ems   alt   hid   

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

题意:

 给出n、m、k ,求出1<=x<=n, 1<=y<=m 且gcd(x,y) == k 的(x,y)的对数

解析:

显然就是求 [1,n/k] 与 [1, m/k]有多少数对的最大公约数是1

莫比乌斯入门题

我们设

    技术分享为满足技术分享技术分享技术分享技术分享的对数

    技术分享为满足技术分享技术分享技术分享技术分享的对数

 那么,很显然技术分享,反演后得到技术分享

我们所需要的答案便是  f(1) = i=1μ(i)*(n/i)*(m/i)  ,求解这个式子我们可以分块求和,复杂度为O(√n)。

最后注意由于题目要求,需要将重复的去掉。

代码如下:

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 
 6 using namespace std;
 7 const int maxn=100010;
 8 
 9 int vis[maxn];
10 int prime[maxn];
11 int cnt;
12 int mu[maxn];
13 int sum[maxn];
14 
15 void init()
16 {
17     memset(vis,0,sizeof(vis));
18     cnt=0;
19     mu[1]=1;
20     for(int i=2;i<maxn;i++)
21     {
22         if(!vis[i])
23         {
24             prime[cnt++]=i;
25             mu[i]=-1;
26         }
27         for(int j=0;j<cnt&&i*prime[j]<maxn;j++)
28         {
29             vis[i*prime[j]]=1;
30             if(i%prime[j])
31                 mu[i*prime[j]]=-mu[i];
32             else
33             {
34                 mu[i*prime[j]]=0;
35                 break;
36             }
37         }
38     }
39     sum[0]=0;
40     for(int i=1;i<maxn;i++)
41         sum[i]=sum[i-1]+mu[i];
42 }
43 
44 int main()
45 {
46     int a,b,c,d,k;
47     init();
48     int T,ca=1;
49     scanf("%d",&T);
50     while(T--)
51     {
52         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
53         printf("Case %d: ",ca++);
54         if(k==0)
55         {
56             printf("0\n");
57             continue;
58         }
59         b=b/k;
60         d=d/k;
61         if(b>d)
62             swap(b,d);
63         long long ans1=0;
64         int last;
65         for(int i=1;i<=b;i=last+1)
66         {
67             last=min(b/(b/i),d/(d/i));
68             ans1+=(long long)(sum[last]-sum[i-1])*(b/i)*(d/i);
69         }
70         long long ans2=0;
71         for(int i=1;i<=b;i=last+1)
72         {
73             last=b/(b/i);
74             ans2+=(long long)(sum[last]-sum[i-1])*(b/i)*(b/i);
75         }
76         long long ans=ans1-ans2/2;
77         printf("%lld\n",ans);
78     }
79     return 0;
80 }
View Code

 

hdu1695 GCD(莫比乌斯入门题)

标签:复杂   sub   入门   print   image   log   ems   alt   hid   

原文地址:http://www.cnblogs.com/yaoyueduzhen/p/6028634.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!