hdu 4746 Mophues 莫比乌斯反演
2015-07-31 16:39
513 查看
Mophues
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 327670/327670 K (Java/Others)Total Submission(s): 910 Accepted Submission(s): 345
Problem Description
As we know, any positive integer C ( C >= 2 ) can be written as the multiply of some prime numbers:
C = p1×p2× p3× ... × pk
which p1, p2 ... pk are all prime numbers.For example, if C = 24, then:
24 = 2 × 2 × 2 × 3
here, p1 = p2 = p3 = 2, p4 = 3, k = 4
Given two integers P and C. if k<=P( k is the number of C's prime factors), we call C a lucky number of P.
Now, XXX needs to count the number of pairs (a, b), which 1<=a<=n , 1<=b<=m, and gcd(a,b) is a lucky number of a given P ( "gcd" means "greatest common divisor").
Please note that we define 1 as lucky number of any non-negative integers because 1 has no prime factor.
Input
The first line of input is an integer Q meaning that there are Q test cases.
Then Q lines follow, each line is a test case and each test case contains three non-negative numbers: n, m and P (n, m, P <= 5×105. Q <=5000).
Output
For each test case, print the number of pairs (a, b), which 1<=a<=n , 1<=b<=m, and gcd(a,b) is a lucky number of P.
Sample Input
2 10 10 0 10 10 1
Sample Output
63 93
Source
2013 ACM/ICPC Asia Regional Hangzhou Online
题目:求1<=a<=n,1<=b<=m ,gcd(a,b) 的质因数个数 <= p的a,b的组合数
莫比乌斯反演:
http://blog.csdn.net/acdreamers/article/details/12871643 详情看这篇博客。写得挺详细。赞~~
如果定义最大公约数为x,
定义函数F(x) = (n/x)*(m/x)
显然最大公约数为x的a,b组合数包含在F(x)中了,但是F(x)还包括了gcd = 2*x,3*x,......,y*x的情况,需要把它们删除
实际是,我们要求得是n/x,m/x的组合中有几组是互质的情况。如果用容斥的方法,我们需要删除包含了质因数2,3,5.。。。。的情况,即减去(n/x)/2*(m/x)/2这种情况
然后因为如10,这样包含两个质因数的情况呗删除两次,又需要加回来。又要加上m/x/10 * n/x/10。
对于每个因数(不只是质因数),会发现只需要加一次,或者减一次即可。然后就是莫比乌斯函数啦。
定义Y(x)为最大公约数为x的组合数,u(x)为x的莫比乌斯函数,那么
Y(x) = F(x)*u(1) + F(x*2)*u(2) + F(x*3)+ u(3) + ............ + F(x*n)*u(n)
枚举x = 1 to n
可以算出没给F(x)的系数,再通过系数*F(x)就能得到答案了。 最后通过分块加速,可以做到n^1/2的优化
-----------------------------------------参考博客写了,我就不啰嗦了
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> using namespace std; #define maxn 500007 //记录质因数个数, int prinum[maxn]; //每个数的u函数 int fu[maxn]; //记录是否为质数 int check[maxn]; //记录u函数的前缀和,第二位表示质因数个数 int usnum[maxn][20]; int call(int j,int i){ if(j % i != 0) return 0; return call(j/i,i)+1; } void init(){ memset(check,0,sizeof(check)); memset(prinum,0,sizeof(prinum)); memset(usnum,0,sizeof(usnum)); memset(fu,0,sizeof(fu)); //筛出质数,并计算每个数的质因数个数 for(int i = 2;i < maxn; i++){ if(check[i]) continue; for(int j = i;j < maxn; j += i){ check[j] = 1; if(j % (i*i) == 0) fu[j] = -1; prinum[j] += call(j,i); if(fu[j] != -1) fu[j]++; } } for(int i = 1;i < maxn; i++) if(fu[i] == -1) fu[i] = 0; else fu[i] = 1 - 2*(fu[i]&1); //如筛素数法,计算每个数的U值之和 for(int i = 1;i < maxn; i++){ for(int j = i;j < maxn; j+=i){ usnum[j][prinum[i]] += fu[j/i]; } } //计算u的前缀和 for(int i = 1;i < maxn; i++){ for(int j = 1;j < 20; j++) usnum[i][j] += usnum[i][j-1]; for(int j = 0;j < 20; j++) usnum[i][j] += usnum[i-1][j]; } } int main(){ init(); int t,n,m,p; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&p); if(n > m) swap(n,m); long long ans = 0; p = min(p,19); int j; if(p > 19) ans = 1ll*n*m; else for(int i = 1;i <= n; i = j + 1){ j = min(n/(n/i),m/(m/i)); ans += (usnum[j][p]-usnum[i-1][p])*1ll*(n/i)*(m/i); } printf("%I64d\n",ans); } return 0; }
相关文章推荐
- UITableView - 2
- ZOJ 2105 Number Sequence(矩阵快速幂)
- 提高android应用ui运行效率
- Error:Cannot build Artifact :war exploded because it is included into a circular depency
- iOS阶段学习第30天笔记( UIViewController—Delegate(代理) )
- (转)UIViewController中各方法调用顺序及功能详解
- hdu 4396 More lumber is required(最短路)
- [leetcode] Implement Stack using Queues
- UIView常用的一些方法小记之setNeedsDisplay和setNeedsLayout
- break和continue
- UI控件---CollectionView
- MenuInflater用法
- 设置UITableviewCell的separatorStyle左边顶格
- easyui combogrid 的查询
- 响应式web设计之CSS3 Media Queries
- Target runtime com.genuitec.runtime.generic.jee50 is not defined
- ue怎样取消保存生成的.bak文件
- HDOJ 题目4339 Query(线段树,单点更新)
- ubuntu-64位 error while loading shared libraries: libuuid.so.1: wrong ELF class: ELFCLASS64
- iOS开发 扩大UIButton的响应区域