ACM学习历程—HDU4675 GCD of Sequence(莫比乌斯)
Description
Alice is playing a game with Bob.
Alice shows N integers a 1, a 2, …, a N, and M, K. She says each integers 1 ≤ a i ≤ M.
And now Alice wants to ask for each d = 1 to M, how many different sequences b 1, b 2, …, b N. which satisfies :
1. For each i = 1…N, 1 ≤ b[i] ≤ M
2. gcd(b 1, b 2, …, b N) = d
3. There will be exactly K position i that ai != bi (1 ≤ i ≤ n)
Alice thinks that the answer will be too large. In order not to annoy Bob, she only wants to know the answer modulo 1000000007.Bob can not solve the problem. Now he asks you for HELP!
Notes: gcd(x 1, x 2, …, x n) is the greatest common divisor of x 1, x 2, …, x n
Input
The input contains several test cases, terminated by EOF.
The first line of each test contains three integers N, M, K. (1 ≤ N, M ≤ 300000, 1 ≤ K ≤ N)
The second line contains N integers: a 1, a 2, ..., a n (1 ≤ a i ≤ M) which is original sequence.
Output
For each test contains 1 lines :
The line contains M integer, the i-th integer is the answer shows above when d is the i-th number.
Sample Input
3 3 33 3 33 5 31 2 3
Sample Output
7 1 059 3 0 1 1
Hint
In the first test case : when d = 1, {b} can be : (1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 2, 2) (2, 1, 1) (2, 1, 2) (2, 2, 1) when d = 2, {b} can be : (2, 2, 2) And because {b} must have exactly K number(s) different from {a}, so {b} can't be (3, 3, 3), so Answer = 0
题目关键在于找出什么东西是可以求的。
之前做过莫比乌斯的题目,一般都是d | gcd的比较好求。
那么考虑对于d | gcd的情况F(d)有多少种?
如果当前数列里面有num[d]个数是d的倍数。
首先由于要改掉k个,那么有n-k个数是不变的,如果这些数有不是d的倍数,那么不满足条件了。
即如果n-k > num[d],F(d) == 0。
于是对于余下的n-k,可以从num[d]个数中选取,即C(num[d], n-k)。
然后对于被改掉了k个数来说,里面肯定有num[d]-(n-k)个数是d的倍数,则有quickPow(m/d-1,num[d]-(n-k))种选法。最后剩余的n-num[i]个数,则有quickPow(m/i, n-num[i])种选法。最后乘起来就是结果了。需要对于0的情况考虑一下。
于是F(d)有了,而F(d) = sum(f(n)) (d|n)。
这一步网上有把F(d)一道一边,f(d)一到另一边计算的。这里采用莫比乌斯反演。
然后C组合数的求法的话,预处理出所有排列数p[]和逆元invp[],这里的invp是用前一个invp[i-1]乘上i的逆元计算的,i的逆元又是用O(n)算法先处理出来的。总的复杂度是O(n)。
快速幂复杂度是logn。
然后莫比乌斯的复杂度是nlogn。
最后总的复杂度是nlogn的。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long
#define MOD 1000000007 using namespace std; const int maxN = ;
int n, m, k;
int num[maxN];
int sum[maxN];
int p[maxN], inv[maxN], invp[maxN];
int u[maxN], prime[maxN];
bool vis[maxN];
int ans[maxN]; //莫比乌斯反演
//F(n)和f(n)是定义在非负整数集合上的两个函数
//并且满足条件F(n) = sum(f(d)) (d|n)
//那么f(n) = sum(u(d)*F(n/d)) (d|n)
//case 1: if d = 1, u(d) = 1
//case 2: if d = p1*p2...pk, (pi均为互异素数), u(d) = (-1)^k
//case 3: else, u(d) = 0;
//性质1: sum(u(d)) (d|n) = 1 (n == 1) or 0 (n > 1)
//性质2: sum(u(d)/d) (d|n) = phi(n)/n
//另一种形式:F(d) = sum(f(n)) (d|n) => f(d) = sum(u(n/d)*F(n)) (d|n)
//线性筛选求莫比乌斯反演函数代码
void mobius()
{
memset(vis, false,sizeof(vis));
u[] = ;
int cnt = ;
for(int i = ; i < maxN; i++)
{
if(!vis[i])
{
prime[cnt++] = i;
u[i] = -;
}
for(int j = ; j < cnt && i*prime[j] < maxN; j++)
{
vis[i*prime[j]] = true;
if(i%prime[j])
u[i*prime[j]] = -u[i];
else
{
u[i*prime[j]] = ;
break;
}
}
}
} void init()
{
mobius();
//***预处理所有i在质数MOD下的逆元
inv[] = ;
for (int i = ; i < maxN; i++)
inv[i] = (LL)inv[MOD%i]*(MOD-MOD/i) % MOD;
p[] = ;
invp[] = inv[];
for (int i = ; i < maxN; ++i)
{
p[i] = (LL)p[i-]*i%MOD;
invp[i] = (LL)invp[i-]*inv[i]%MOD;
}
} void input()
{
memset(num, , sizeof(num));
int tmp;
for (int i = ; i < n; ++i)
{
scanf("%d", &tmp);
num[tmp]++;
} for (int i = ; i <= m; ++i)
{
for (int j = i*; j <= m; j += i)
num[i] += num[j];
}
} inline int C(int x, int y)
{
int ans;
ans = (LL)p[x]*invp[x-y]%MOD;
ans = (LL)ans*invp[y]%MOD;
return ans;
} //快速幂m^n
LL quickPow(LL x, int n)
{
if (n == )
return ;
if (x == )
return ;
LL a = ;
while (n)
{
a *= n& ? x : ;
a %= MOD;
n >>= ;
x *= x;
x %= MOD;
}
return a;
} void work()
{
memset(sum, , sizeof(sum));
memset(ans, , sizeof(ans));
for (int i = ; i <= m; ++i)
{ if (num[i] < n-k)
sum[i] = ;
else
{
sum[i] = C(num[i], n-k)*quickPow(m/i, n-num[i])%MOD;
sum[i] = quickPow(m/i-, num[i]-(n-k))*sum[i]%MOD;
}
}
for (int i = ; i <= m; ++i)
{
for (int j = i; j <= m; j += i)
{
ans[i] += (LL)u[j/i]*sum[j]%MOD;
ans[i] = (ans[i]%MOD+MOD)%MOD;
}
}
for (int i = ; i <= m; ++i)
{
if (i != )
printf(" ");
printf("%d", ans[i]);
}
printf("\n");
} int main()
{
//freopen("test.in", "r", stdin);
init();
while (scanf("%d%d%d", &n, &m, &k) != EOF)
{
input();
work();
}
return ;
}
ACM学习历程—HDU4675 GCD of Sequence(莫比乌斯)的更多相关文章
- ACM学习历程—HDU1695 GCD(容斥原理 || 莫比乌斯)
Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = ...
- hdu4675 GCD of Sequence 莫比乌斯+组合数学
/** 题目:hdu4675 GCD of Sequence 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4675 题意:给定n个数的a数组,以及m,k: ...
- ACM学习历程——HDU 5014 Number Sequence (贪心)(2014西安网赛)
Description There is a special number sequence which has n+1 integers. For each number in sequence, ...
- 数学--数论--HDU 4675 GCD of Sequence(莫比乌斯反演+卢卡斯定理求组合数+乘法逆元+快速幂取模)
先放知识点: 莫比乌斯反演 卢卡斯定理求组合数 乘法逆元 快速幂取模 GCD of Sequence Alice is playing a game with Bob. Alice shows N i ...
- ACM学习历程—ZOJ 3868 GCD Expectation(莫比乌斯 || 容斥原理)
Description Edward has a set of n integers {a1, a2,...,an}. He randomly picks a nonempty subset {x1, ...
- ACM学习历程—HYSBZ 2818 Gcd(欧拉函数 || 莫比乌斯反演)
Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. Input 一个整数N Output 如题 Sample Input 4 Sam ...
- ACM学习历程—HDU4746 Mophues(莫比乌斯)
Description As we know, any positive integer C ( C >= 2 ) can be written as the multiply of some ...
- ACM学习历程—HDU5667 Sequence(数论 && 矩阵乘法 && 快速幂)
http://acm.hdu.edu.cn/showproblem.php?pid=5667 这题的关键是处理指数,因为最后结果是a^t这种的,主要是如何计算t. 发现t是一个递推式,t(n) = c ...
- ACM学习历程—POJ3090 Visible Lattice Points(容斥原理 || 莫比乌斯)
Description A lattice point (x, y) in the first quadrant (x and y are integers greater than or equal ...
随机推荐
- We7的区县站点群建设策略
一.解决门户和委办局.乡镇的互动 构建以区县政府门户为主站,各委办局.乡镇为子站的站点群体系: 基于统一的信息体系,实现分级授权.统一管理的功能.各网站能够有独立的页面展现和管理后台,同一时候网站之间 ...
- SVM支持向量机
支持向量机(Support Vector Machine,SVM)是效果最好的分类算法之中的一个. 一.线性分类器: 一个线性分类器就是要在n维的数据空间中找到一个超平面,通过这个超平面能够把两类数据 ...
- js父页面和子页面之间传值
今天和朋友一块讨论,怎样通过js在父页面和子页面之间传值的问题,总结例如以下: 需求描写叙述:父页面有多个子页面.实如今父页面点击子页面,传值到子页面. 看着非常easy,试了好久.主要纠结在怎样获取 ...
- ios上ZXing库的配置流程
本文转载至 http://blog.csdn.net/louercab/article/details/26448587 步骤 首先,用Xcode创建我们的demo, 取名TestZXing(根据自己 ...
- SQLServer2008 统计表占用空间
1.查看一张表占用的空间大小 EXEC sp_spaceused '表' 1.查看一个数据库中所有表占用空间大小 EXEC sp_MSforeachtable 'sp_spaceused " ...
- vim vimdiff diff 使用及命令
vim: vim 从 vim7 开始加入了多标签切换的功能, 相当于多窗口. 之前的版本虽然也有多文件编辑功能, 但是总之不如这个方便啦.用法::tabnew [++opt选项] [+cmd] 文件 ...
- Data Structure Binary Tree: How to determine if a binary tree is height-balanced?
http://www.geeksforgeeks.org/how-to-determine-if-a-binary-tree-is-balanced/ #include <iostream> ...
- svn及git使用笔记
这周发生好几件大事: 谷歌发布SHA-1安全加密碰撞实例 Cloudflare 泄露网络会话中的加密数据 linux内核漏洞 CVE-2017-6074 加密在网络中越来越受关注,目前github的提 ...
- nginx gzip 压缩设置
mime.types 中包含所有文件的类型,不知道的可以去里面查询 gzip配置的常用参数 gzip on|off; #是否开启gzip gzip_buffers 32 4K| 16 8K #缓冲( ...
- EntityFramework 学习 一 Entity Framework 查询设计
First/FirstOrDefault: using (var ctx = new SchoolDBEntities()) { var student = (from s in ctx.Studen ...