hdu1695GCD(莫比乌斯反演初步)
2015-09-22 15:46
239 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695
题目大意:输入a,b,c,d,k,求出从a到b和从c到d中最大公约数为k数的对数。其中a和c一定为1。注意的是 ,1,2和2,1值算1对。
解题:根据莫比乌斯反演解题。设F(n)表示最大公约数为n的倍数的数有多少对,设f(d)表示最大公约数恰为d的数有多少对。
则F(N)=f(d1)+f(d2)+...+f(dn),N%di==0。
由莫比乌斯反演得f(d)=mu[N1]*F(N1)+mu[N2]*F(N2)+...mu[Nn]*F(Nn),Ni%d==0。
这题要求GCD=k,其实只要求1~b/k和1~d/k中GCD=1即可。
题目大意:输入a,b,c,d,k,求出从a到b和从c到d中最大公约数为k数的对数。其中a和c一定为1。注意的是 ,1,2和2,1值算1对。
解题:根据莫比乌斯反演解题。设F(n)表示最大公约数为n的倍数的数有多少对,设f(d)表示最大公约数恰为d的数有多少对。
则F(N)=f(d1)+f(d2)+...+f(dn),N%di==0。
由莫比乌斯反演得f(d)=mu[N1]*F(N1)+mu[N2]*F(N2)+...mu[Nn]*F(Nn),Ni%d==0。
这题要求GCD=k,其实只要求1~b/k和1~d/k中GCD=1即可。
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; #define ll long long const int MAXN = 1000000; bool check[MAXN+10]; int prime[MAXN+10]; int mu[MAXN+10]; void Get_mu() { memset(check,0,sizeof(check)); int kk=0; mu[1]=1; for(int i=2;i<=MAXN;i++) { if(!check[i]) { prime[kk++]=i; mu[i]=-1; } for(int j=0;j<kk;j++) { if(prime[j]*i>MAXN) break; check[i*prime[j]]=true; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } } int main() { Get_mu(); int t,a,b,d,k,Case=1; scanf("%d",&t); while(t--) { scanf("%d%d%d%d%d",&a,&b,&a,&d,&k); if(k==0) { printf("Case %d: 0\n",Case++); continue; } if(b>d) swap(b,d); b=b/k; d=d/k; ll s=0,ss=0; for(int i=1;i<=b;i++) s+=(ll)mu[i]*(b/i)*(d/i); for(int i=1;i<=b;i++) ss+=(ll)mu[i]*(b/i)*(b/i); printf("Case %d: %lld\n",Case++,s-ss/2); } return 0; }
相关文章推荐
- Lua和C语言的交互详解
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- 探讨C语言的那些小秘密之断言
- C语言实现BMP转换JPG的方法
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置
- C语言查找数组里数字重复次数的方法
- C语言泛型编程实例教程
- C语言中使用lex统计文本文件字符数
- 在C语言中转换时间的基本方法介绍
- C语言进制转换代码分享