题意:

给出\(M\)和\(a数组\),询问每一个\(d\in[1,M]\),有多少组数组满足:正好修改\(k\)个\(a\)数组里的数使得和原来不同,并且要\(\leq M\),并且\(gcd(a_1,a_2,\dots,a_n)=d\)。

思路:

对于每一个\(d\),即求\(f(d)\):修改\(k\)个后\(gcd(a_1,a_2,\dots,a_n)=d\)的对数。

那么假设\(F(d)\):修改\(k\)个后\(gcd(a_1,a_2,\dots,a_n)\)是\(d\)倍数的对数。故:

\[f(k) = \sum_{k|d}\mu(\frac{d}{k})F(d)
\]

打表求\(F(d)\)即可。假设\(num[d]\)为\(a\)中是\(d\)倍数的数量,则

\[F(d)=(\frac{M}{d})^{n-num[d]}*C_{num[d]}^{k-(n-num[d])}*(\frac{M}{d}-1)^{k-(n-num[d])}
\]

然后\(nlogn\)打出\(num\)数组即可。

思考:

这样的打表法是\(nlogn\)的:

证明 O(n/1+n/2+…+n/n)=O(nlogn)

for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
num[a[i]]++;
}
for(int i = 1; i <= m; i++){
for(int j = i + i; j <= m; j += i){
num[i] += num[j];
}
}

这样是\(n\sqrt n\)的

for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
for(int j = 1; j <= sqrt(a[i]); j++){
if(a[i] % j == 0){
num[j]++;
if(j * j != a[i]) num[a[i] / j]++;
}
}
}

代码:

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const ull seed = 131;
const ll MOD = 1000000007;
using namespace std; int mu[maxn], vis[maxn];
int prime[maxn], cnt;
ll fac[maxn], inv[maxn];
ll ppow(ll a, ll b){
ll ret = 1;
while(b){
if(b & 1) ret = ret * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ret;
}
void init(int n){
memset(vis, 0, sizeof(vis));
memset(mu, 0, sizeof(mu));
cnt = 0;
mu[1] = 1;
for(int i = 2; i <= n; i++) {
if(!vis[i]){
prime[cnt++] = i;
mu[i] = -1;
}
for(int j = 0; j < cnt && prime[j] * i <= n; j++){
vis[prime[j] * i] = 1;
if(i % prime[j] == 0) break;
mu[i * prime[j]] = -mu[i];
}
} fac[0] = inv[0] = 1;
for(int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % MOD;
inv[n] = ppow(fac[n], MOD - 2);
for(int i = n - 1; i >= 1; i--) inv[i] = (i + 1LL) * inv[i + 1] % MOD;
}
ll C(int n, int m){
return fac[n] * inv[m] % MOD * inv[n - m] % MOD;
}
int num[maxn], a[maxn];
//num[i]:是i的倍数的个数
ll F[maxn], f[maxn];
int main(){
init(3e5);
int n, m, k;
while(~scanf("%d%d%d", &n, &m, &k)){
memset(num, 0, sizeof(num));
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
num[a[i]]++;
}
for(int i = 1; i <= m; i++){
for(int j = i + i; j <= m; j += i){
num[i] += num[j];
}
}
for(int i = 1; i <= m; i++){
int no = n - num[i];
if(no > k) F[i] = 0;
else{
F[i] = ppow(m / i, no) * C(num[i], k - no) % MOD * ppow(m / i - 1, k - no) % MOD;
}
} for(int i = 1; i <= m; i++){
f[i] = 0;
for(int j = i; j <= m; j += i){
f[i] += mu[j / i] * F[j];
f[i] %= MOD;
}
printf("%lld%c", (f[i] % MOD + MOD) % MOD, i == m? '\n' : ' ');
} }
return 0;
}

HDU 4675 GCD of Sequence(莫比乌斯反演 + 打表注意事项)题解的更多相关文章

  1. 数学--数论--HDU 4675 GCD of Sequence(莫比乌斯反演+卢卡斯定理求组合数+乘法逆元+快速幂取模)

    先放知识点: 莫比乌斯反演 卢卡斯定理求组合数 乘法逆元 快速幂取模 GCD of Sequence Alice is playing a game with Bob. Alice shows N i ...

  2. HDU - 4675 GCD of Sequence (莫比乌斯反演+组合数学)

    题意:给出序列[a1..aN],整数M和k,求对1-M中的每个整数d,构建新的序列[b1...bN],使其满足: 1. \(1 \le bi \le M\) 2. \(gcd(b 1, b 2, -, ...

  3. HDU 4675 GCD of Sequence (2013多校7 1010题 数学题)

    GCD of Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)T ...

  4. HDU 4675 GCD of Sequence(容斥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4675 题意:给出n,m,K,一个长度为n的数列A(1<=A[i]<=m).对于d(1< ...

  5. hdu 4675 GCD of Sequence

    数学题! 从M到1计算,在计算i的时候,算出原序列是i的倍数的个数cnt: 也就是将cnt个数中的cnt-(n-k)个数变掉,n-cnt个数变为i的倍数. 且i的倍数为t=m/i; 则符合的数为:c[ ...

  6. 【CJOJ2512】gcd之和(莫比乌斯反演)

    [CJOJ2512]gcd之和(莫比乌斯反演) 题面 给定\(n,m(n,m<=10^7)\) 求 \[\sum_{i=1}^n\sum_{j=1}^mgcd(i,j)\] 题解 首先把公因数直 ...

  7. HDU 2841 Visible Trees(莫比乌斯反演)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2841 题意:给n*m的矩阵(从(1,1)开始编号)格子,每个格子有一棵树,人站在(0,0)的位置,求可 ...

  8. hdu4675 GCD of Sequence 莫比乌斯+组合数学

    /** 题目:hdu4675 GCD of Sequence 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4675 题意:给定n个数的a数组,以及m,k: ...

  9. bnu——GCD SUM (莫比乌斯反演)

    题目:GCD SUM 题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=39872 算法:莫比乌斯反演.优化 #include<stdio.h& ...

随机推荐

  1. 并发条件队列之Condition 精讲

    1. 条件队列的意义 Condition将Object监控器方法( wait , notify和notifyAll )分解为不同的对象,从而通过与任意Lock实现结合使用,从而使每个对象具有多个等待集 ...

  2. hadoop及NameNode和SecondaryNameNode工作机制

    hadoop及NameNode和SecondaryNameNode工作机制 1.hadoop组成 Common MapReduce Yarn HDFS (1)HDFS namenode:存放目录,最重 ...

  3. 类型检查和鸭子类型 Duck typing in computer programming is an application of the duck test 鸭子测试 鸭子类型 指示编译器将类的类型检查安排在运行时而不是编译时 type checking can be specified to occur at run time rather than compile time.

    Go所提供的面向对象功能十分简洁,但却兼具了类型检查和鸭子类型两者的有点,这是何等优秀的设计啊! Duck typing in computer programming is an applicati ...

  4. python基础(格式化输出、基本运算符、编码)

    1,格式化输出. 现有一练习需求,问用户的姓名.年龄.工作.爱好 ,然后打印成以下格式 ------------ info of Alex Li ----------- Name : Alex Li ...

  5. LOJ10019生日蛋糕

    Mr.W 要制作一个体积为 N*π 的 M 层生日蛋糕,每层都是一个圆柱体. 设从下往上数第 i 蛋糕是半径为 R_i,高度为 H_i 的圆柱.当 i<M 时,要求 R_i>R_{i+1} ...

  6. flutter环境部署

    一,xcode开发环境配置问题记录 1,Signing for "Runner" requires a development team xcode需要配置AppleID: 1,X ...

  7. Docker中运行nginx

    Docker中运行nginx 1.Docker中运行nginx 2.配置文件 2.1 nginx.conf 2.2 default.conf 3.docker的镜像可以挂什么卷 部分内容原文地址: C ...

  8. spark SQL(三)数据源 Data Source----通用的数据 加载/保存功能

    Spark SQL 的数据源------通用的数据 加载/保存功能 Spark SQL支持通过DataFrame接口在各种数据源上进行操作.DataFrame可以使用关系变换进行操作,也可以用来创建临 ...

  9. C语言之数据在内存中的存储

    C语言之数据在内存中的存储 在我们学习此之前,我们先来回忆一下C语言中都有哪些数据类型呢? 首先我们来看看C语言中的基本的内置类型: char //字符数据类型 short //短整型 int //整 ...

  10. acid解释

    原子性A:一个事务内部的所有操作都是不可分割的,这叫原子性.一致性C:事务内部的所有操作要么都成功,要么都失败.隔离性I:事务与事务之间永远不相见.持久性D:就是说数据最终是落到磁盘永久保存的.