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 ...
随机推荐
- Centos 安装libreoffice 生成office 报错信息见内容
个人博客:https://blog.sharedata.info/ 错误信息:/opt/libreoffice5.2/program/soffice.bin: error while loading ...
- EasyDSS流媒体服务器灵活地帮助用户实现摄像机RTSP转RTMP直播功能
简要描述 今天突然接到国内某上市公司同事打来的技术咨询电话,经过简单的沟通,大概所描述的需求是: 1.目前现场有非常多的摄像机资源需要接入: 2.需要将摄像机的RTSP流转成RTMP流接入到微信小程序 ...
- HealthKit详解
1. 导入HealthKit框架 #import <HealthKit/HealthKit.h> 2. 判断设备是否支持HealthKit HealthKit是iOS8加入的API Hea ...
- springboot + swagger2 学习笔记
引入步骤 1.添加依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springf ...
- 基于flask的web微信
web微信 1.扫码获取头像 当你打开web微信的时候,因为http是无状态的,web微信如何实时的获取用户的扫码动作? 那么这里用到的是长轮询的方式. from flask import Flask ...
- windows环境下JDK1.8安装
jdk的安装,在Windows环境下没有什么特殊的选项,只需要“傻瓜式”安装就行(下一步). 如果说有的话,那就是你安装的路径,默认是c盘下的路径,可以根据自己的喜好,安装到自己的意愿目录: 当然,j ...
- memcpy使用
void memcpy(void dest, const void *src, size_t n); 功能编辑 从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置 ...
- Block的详细介绍
关于block的介绍 ==ios中的内存空间分级== 栈区 存放函数参数值.局部变量.函数返回地址等,函数跳转跳转时现场保护(寄存器),这些系统都会帮我们自动实现,无需我们干预. 所以大量的局部变量, ...
- ssl和tls
HTTP 是一个网络协议,是专门用来帮你传输 Web 内容 SSL 是Secure Sockets Layer 为啥要发明 SSL 这个协议捏?因为原先互联网上使用的 HTTP 协议是明文的,存在很多 ...
- LISP
LISP是一种通用高级计算机程序语言,长期以来垄断人工智能领域的应用.LISP作为因应人工智能而设计的语言,是第一个声明式系内函数式程序设计语言,有别于命令式系内过程式的C.Fortran和面向对象的 ...