题意:

给出\(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. MySQL中UPDATE语句里SET后使用AND的执行过程和结果分析

    使用SQL中的UPDATE关键字更新多个字段值时,SET后面的更新字段应该使用逗号而不能用AND.虽然用AND不会报错,但会使更新结果错误,下面我将通过场景来分析当我们使用AND时SQL的执行过程和为 ...

  2. ElasticSearch-IK分词器和集成使用

    1.查询存在问题分析 在进行字符串查询时,我们发现去搜索"搜索服务器"和"钢索"都可以搜索到数据: 而在进行词条查询时,我们搜索"搜索"却没 ...

  3. ovsdb-client命令

    ovsdb-server 的命令行接口. 查看有哪些数据库: ovsdb-client list-dbs [server] 查看数据库 schema: ovsdb-client get-schema ...

  4. 从零搭建一个IdentityServer——集成Asp.net core Identity

    前面的文章使用Asp.net core 5.0以及IdentityServer4搭建了一个基础的验证服务器,并实现了基于客户端证书的Oauth2.0授权流程,以及通过access token访问被保护 ...

  5. 支持 gRPC 长链接,深度解读 Nacos 2.0 架构设计及新模型

    支持 gRPC 长链接,深度解读 Nacos 2.0 架构设计及新模型 原创 杨翊(席翁) 阿里巴巴云原生 2020-12-28    

  6. Turbo Boyer-Moore algorithm

    MySQL :: MySQL 8.0 Reference Manual :: 8.3.9 Comparison of B-Tree and Hash Indexes https://dev.mysql ...

  7. Servlet中的一些注意事项

    servlet中的一些注意事项 1 什么是servlet? 1)Servlet是Sun公司制定的一套技术标准,包含与Web应用相关的一系列接口,是Web应用实现方式的宏观解决方案.而具体的Servle ...

  8. 动态库与静态库的学习 博主写的很好 静态库 编译的时候 需要加上 static 动态库编译ok运行不成功就按照文章中的方法修改

    来源连接   http://www.cnblogs.com/skynet/p/3372855.html C++静态库与动态库 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库 ...

  9. 慕课网金职位 Java工程师2020 百度网盘下载

    百度网盘链接:https://pan.baidu.com/s/1xshLRO3ru0LAsQQ0pE67Qg 提取码:bh9f 如果失效加我微信:610060008[视频不加密,资料代码齐全,超清一手 ...

  10. Redis集群数据没法拆分时的搭建策略

    在上一篇文章中,针对服务器单点.单例.单机存在的问题: 单点故障 容量有限 可支持的连接有限(性能不足) 提出了解决的办法:根据AKF原则搭建集群,大意是先X轴拆分,创建单机的镜像,组成主主.主备.主 ...