繁凡出品的全新系列:解题报告系列 —— 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 111 为基准。


这样大家在学习算法的时候就可以执行这样的流程:

%
阅读我的【学习笔记】 / 【算法全家桶】学习算法 ⇒\Rightarrow⇒ 阅读我的相应算法的【解题报告】获得高质量题单 ⇒\Rightarrow⇒ 根据我的一句话题解的提示尝试自己解决问题 ⇒\Rightarrow⇒ 点开我的详细题解链接学习巩固(好耶)
%
题单链接:【解题报告】快速沃尔什变换FWT(ICPC / CCPC / NOIP / NOI / CF / AT / NC / P / BZOJ)超高质量题解 !!!

C、(牛客练习赛41 F)简单数学题(数论 + FWT)(3.5)

Link

https://ac.nowcoder.com/acm/contest/373/F

Problem

定义如下函数:
f(x)={1x=1max⁡{t∣xmodt=0&&∣μ(t)∣=1}x≥2\ f(x)= \begin{cases} 1 & {x=1}\\ \max\{ t\ |\ {x \bmod t = 0}\ \&\&\ |\mu(t)| = 1 \}& {x \geq 2} \end{cases} f(x)={1max{t ∣ xmodt=0 && ∣μ(t)∣=1}​x=1x≥2​

其中μ(t)\mu(t)μ(t)为莫比乌斯函数,详见:https://en.wikipedia.org/wiki/M%C3%B6bius_function

对于任何整数x\ x x,若有 x=p1n1p2n2...pknkx = p_{1}^{n_{1}}p_{2}^{n_{2}}...p_{k}^{n_{k}}x=p1n1​​p2n2​​...pknk​​ ,其中pi\ p_{i} pi​是x\ x x 第i\ i i 大的质因子,则

g(x)=p1β(n1)p2β(n2)...pkβ(nk)g(x) = p_{1}^{\beta(n_{1})}p_{2}^{\beta(n_{2})}...p_{k}^{\beta(n_{k})}g(x)=p1β(n1​)​p2β(n2​)​...pkβ(nk​)​​

β(x)={0x is even1x is odd\beta(x)= \begin{cases} 0& \text{x is even}\\ 1& \text{x is odd} \end{cases}β(x)={01​x is evenx is odd​

现在定义F(a,b,c)=g(f(a)∗f(b)∗f(c))\ F(a, b, c) = g(f(a)*f(b)*f(c)) F(a,b,c)=g(f(a)∗f(b)∗f(c))

并给出三个长度均为n\ n n 的数列

A1A2A3...An\ A_{1}A_{2}A_{3}...A_{n} A1​A2​A3​...An​​

B1B2B3...Bn\ B_{1}B_{2}B_{3}...B_{n} B1​B2​B3​...Bn​​

C1C2C3...Cn\ C_{1}C_{2}C_{3}...C_{n} C1​C2​C3​...Cn​

对于某个整数z\ z z,如有 z=F(Ai,Bj,Ck)(1≤i,j,k≤n)\ z = F(A_{i}, B_{j}, C_{k})(1 \leq i,j,k \leq n) z=F(Ai​,Bj​,Ck​)(1≤i,j,k≤n)

则称GF(i,j,k)\ GF(i, j, k) GF(i,j,k)为z的一种表示

设S\ S S 集合为 S={z∣z=F(Ai,Bj,Ck),1≤i,j,k≤n}S = \{ z|z=F(A_{i}, B_{j}, C_{k}),1 \leq i,j,k \leq n \}S={z∣z=F(Ai​,Bj​,Ck​),1≤i,j,k≤n} ,∣Z∣\ {|Z|} ∣Z∣为 S\ S S 中元素的个数

求 ans=∑i=1∣Z∣zikians = \sum_{i=1}^{|Z|}{z_{i} k_{i}}ans=∑i=1∣Z∣​zi​ki​ ,其中 ziz_{i}zi​ 是集合S\ S S 的第i\ i i 个元素,其中 kik_{i}ki​ 为 ziz_{i}zi​ 的不同的表示的个数。答案对109+7\ 10^{9}+7 109+7 取模。

注意:对于一个数 z\ z z ,如果z=F(Ai1,Bj1,Ck1))=F(Ai2,Bj2,Ck2))\ z = F(A_{i_{1}}, B_{j_{1}}, C_{k_{1}})) = F(A_{i_{2}}, B_{j_{2}}, C_{k_{2}})) z=F(Ai1​​,Bj1​​,Ck1​​))=F(Ai2​​,Bj2​​,Ck2​​)) ,只要 i1≠i2orj1≠j2ork1≠k2i_{1}\neq i_{2}\ or\ j_{1}\neq j_{2}\ or\ k_{1}\neq \ k_{2}i1​​=i2​ or j1​​=j2​ or k1​​= k2​ ,那么我们说 zzz 的这两种表示的两种不同的表示。

1≤n≤105,Ai,Bi,Ci≤10181\le n\le 10^5,A_i,B_i,C_i\le10^{18}1≤n≤105,Ai​,Bi​,Ci​≤1018,保证后三行输入的所有整数每个数的最大质因子不会超过71\ 71 71。

Sample Input

2
2 3
4 6
6 10

Sample Output

72

Hint

一句话题解: 看上去比较麻烦,但是搞清楚每个函数的作用以后一步步分析即可。关键还是在于如何引出异或操作,我们的 fff 函数实际上得到的是一些质数的一次幂的乘积,而题目中告诉我们了所含质因数 ≤71\le 71≤71 ,所以我们可以预处理一下,那么一共就只有 20 个数了,那么我们的 fff 函数的实际意义就变成了从 20 个质数中选择若干个质数,那么对于每一个质数来说就只有选或者不选两种情况,所以可以用状态压缩,压成一个二进制数,这样我们就可以使用位运算了 ~ 能想到这一点就会发现这几乎就是一个 FWT 的模板题了,再往后就是正常的变换了,同样的我们只需要想办法将进行位运算的数变成下标即找到一个下标的属性的序列,将他们卷起来求方案数 kik_iki​ 最后求 ans 即可。

Solution

题目比较麻烦,一步一步来分析。

首先,分析 f(x)f(x)f(x), f(x)f(x)f(x) 求的是一个最大的 ttt ,满足 ttt 是 xxx 的约数,且 ttt 是质数一次幂的乘积。最大,所以肯定是所有质因子的乘积。

由于题目中规定质因数不会超过 717171 ,所以我们可以先预处理出 222 到 717171 的质数表,一共只有 202020 个,我们输入的数组,先将输入的每个数组处理成 f(a[i])f(a[i])f(a[i]),因为我们只需要知道选了哪些质数就行了,也就意味着每个质数只有 000 或者 111 两种选择,我们得到的 f(x)f(x)f(x) 的值就可以表示成从质数表里挑选一些数的乘积,这样我们的 f(x)f(x)f(x) 就可以表示成将 xxx 质因数分解后选择质数表里的某些质数的下标压缩成一个二进制数 maskmaskmask 来表示这个状态 f(x)f(x)f(x),也就是状态压缩,一共只有 220=1e62^{20} = 1e6220=1e6。

例如 x=10=2×5x=10=2\times 5x=10=2×5,即选择第 000 个质数 222 ,第 222 个质数 555 ,所以mask=101=5mask=101=5mask=101=5。则 num[mask] ++ ; ,其中 num 表示一个质数集,++ 意味着这个 xxx 属于这个质数集,可表示成这个质数集的数的个数 +1。

然后分析 g(x)g(x)g(x),结合 β(x)\beta(x)β(x) 和 F(a,b,c)F(a,b,c)F(a,b,c) 发现实际上就是将 f(a),f(b),f(c)f(a),f(b),f(c)f(a),f(b),f(c) 三个数的相同质因数的次幂( 0 或者 1 )的异或值作为新次幂的数的乘积。而我们的 f(a),f(b),f(c)f(a),f(b),f(c)f(a),f(b),f(c) 已经是被处理成了二进制的形式的数,所以直接异或就行了。

这样问题就转变成了处理素数集 f(x)f(x)f(x) 之间的关系也就是集合与集合之间的异或操作,也就是经典 快速沃尔什变换(FWT),FWT 可以将两个集合按照下标卷起来。

因为我们要统计的是方案数 kik_iki​, 而显然 zzz 的出现次数 kz=numa×numb×numck_z=num_a\times num_b\times num_ckz​=numa​×numb​×numc​,其中 a⊕b⊕c=za\oplus b\oplus c=za⊕b⊕c=z。

即:

kz=∑z=a⊕b⊕cnuma×numb×numck_z=\sum_{z=a\oplus b\oplus c}num_a\times num_b\times num_c kz​=z=a⊕b⊕c∑​numa​×numb​×numc​

实际意义就是 aia_iai​ 的个数是 numainum_{a_i}numai​​, bib_ibi​ 的个数是 numbinum_{b_i}numbi​​,那么 aia_iai​ 和 bib_ibi​ 异或起来组成的 zzz 的 方案数 即题目中要求的不同的表示的个数 kik_iki​ 就是 numai×numbinum_{a_i}\times num_{b_i}numai​​×numbi​​。

求出 kik_iki​ ,答案为 ans=∑i=1∣Z∣zikians = \sum_{i=1}^{|Z|}{z_{i} k_{i}}ans=∑i=1∣Z∣​zi​ki​,我们枚举状压的那个二进制数,将枚举到的 iii 还原为 zzz ,加上 z×kiz\times k_iz×ki​ (没有这个 zzz 的话 ki=0k_i=0ki​=0 不影响)即可。

是不是很简单

Code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>using namespace std;
typedef long long ll;
typedef int itn;
const int N = (1 << 20) + 7, mod = 1e9 + 7;
const ll INF = 4e18;
itn dcnt;
#define de(x) cout << x << " x" << endl
#define de1() cout << ++ dcnt << "ok" << endl
itn n, m;
ll a[N], b[N], c[N], k[N];
ll primes[N], cnt_primes;
int cnt;
bool vis[N];void init()
{for(int i = 2; i <= 71; ++ i) {if(vis[i] == 0) primes[cnt_primes ++ ] = 1ll * i;for(int j = 0; j < cnt_primes && primes[j] * i <= 71; ++ j) {vis[i * primes[j]] = true;if(i % primes[j] == 0) break;}}
}ll qpow(ll a, ll b)
{ll res = 1;while(b) {if(b & 1) res = 1ll * res * a % mod;a = 1ll * a * a % mod;b >>= 1;}return res % mod;
}int inv2 = qpow(2, mod - 2);void XOR(ll *f, int n, int x = 1)
{for(int o = 2; o <= n; o <<= 1) {for(int i = 0, k = o >> 1; i < n; i += o) {for(int j = 0; j < k; ++ j) {ll X = f[i + j];ll Y = f[i + j + k];f[i + j] = (1ll * X + Y) % mod;f[i + j + k] = (1ll * (X - Y) % mod + mod) % mod;if(x == -1) {f[i + j] = (1ll * f[i + j] * inv2) % mod;f[i + j + k] = (1ll * f[i + j + k] * inv2) % mod;}}}}
}void solve(ll *a)//求 f(a)
{ll x;for(int i = 1; i <= n; ++ i) {scanf("%lld", &x);ll cnt = 0, mask = 0;for(int j = 0; j < cnt_primes && x > 1; ++ j) {cnt = 0;ll p = primes[j];while(x % p == 0) {x /= p;cnt ++ ;}if(cnt)mask |= 1 << j;//选择了 j 这个数}a[mask] ++ ;}
}ll cal(int x)
{ll res = 1;for(int i = 0; i < cnt_primes; ++ i) {if(x & (1 << i)) res = 1ll * res * primes[i] % mod;}return res;
}int main()
{init();scanf("%d", &n);solve(a), solve(b), solve(c);XOR(a, 1 << 20), XOR(b, 1 << 20), XOR(c, 1 << 20);for(int i = 0; i < 1 << 20; ++ i)k[i] = 1ll * a[i] * b[i] % mod * c[i] % mod;XOR(k, 1 << 20, -1);ll ans = 0;for(int i = 0; i < 1 << 20; ++ i) {ans = (1ll * ans + cal(i) * k[i] % mod) % mod;}printf("%lld\n", ans);return 0;
}

解题报告(一)C、(牛客练习赛41 F)简单数学题(数论 + FWT)(3.5)相关推荐

  1. 【解题报告】2021牛客寒假算法基础集训营4

    [解题报告]2021牛客寒假算法基础集训营4 前面的话 A :九峰与签到题 | 模拟 (签到题) B: 武辰延的字符串 | exKMP D :温澈滢的狗狗 | 二分 E: 九峰与子序列 | d p d ...

  2. 牛客练习赛29: F. 算式子

    链接:https://www.nowcoder.com/acm/contest/211/F 来源:牛客网 题目描述 给定  个整数  .保证  . 对于每个  ,求出 .为了避免过量输出,你只需要将所 ...

  3. 牛客练习赛50 F tokitsukaze and Another Protoss and Zerg(分治NTT)

    一些废话: 写完上一题(分治FFT)之后记起之前牛客写的这道题,题解是用启发式NTT,每次选两个项数最小的合并,当时没有整理NTT的模板所以就先mark了,今天受到分治FFT的启发,想用分治NTT来解 ...

  4. 牛客练习赛 43 F Tachibana Kanade Loves Game 容斥原理(Java版ac)

    链接:https://ac.nowcoder.com/acm/contest/548/F 来源:牛客网 题目描述 立华奏是一个天天打比赛的萌新. 省选将至,萌新立华奏深知自己没有希望进入省队,因此开始 ...

  5. 牛客练习赛63 F 牛牛的树行棋 (SG函数+树差分)

    链接:https://ac.nowcoder.com/acm/contest/5531/F 来源:牛客网 牛牛的树行棋 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K, ...

  6. 牛客练习赛41 b 666RPG (01背包)

    时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 在欧美,"666"是个令人 ...

  7. 牛客练习赛41 D.最小相似度(思维+bfs)

    传送门 给定nnn个长mmm位的二进制串 求一个二进制串TTT,定义valival_ivali​是TTT与第iii个二进制串相同的位数 使得max(val1,val2....valn)max(val_ ...

  8. 【牛客网】牛客练习赛19 F 算式子【数学--递推 、前缀、数字】

    传送门:算式子 花了一些时间理解AC的代码,震惊,代码真的是短小精悍,推理能力很强亦或者是做题多,见的多. 能够理解里面的逻辑真的挺难的 题意 给定n,m,\(1\le x\le m\),求\(\su ...

  9. 牛客练习赛43 f Tachibana Kanade Loves Game

    题目链接 题目描述 立华奏是一个天天打比赛的萌新. 省选将至,萌新立华奏深知自己没有希望进入省队,因此开始颓废.她正在颓废一款名为<IODS 9102>的游戏. 在游戏中,立华奏拥有 k ...

最新文章

  1. html5 作业调度,Net作业调度(五)—quartz.net动态添加job设计
  2. 升降压斩波电路matlab,升降压斩波电路matlab仿真.doc
  3. JAVA-retry 重试
  4. 九度 1376 最近零子序列
  5. linux 嵌入式 人工智能,嵌入式人工智能有哪些相关技术
  6. AS3学习笔记(一)基础知识
  7. 2021年北京理工大学ACM CLUB清明节组队训练赛
  8. 1.5 案例:多项式曲线拟合的比较
  9. 编写一个UNIX文件系统
  10. C# 如何给Excel添加水印
  11. 规则引擎Drools使用 第十一篇 Drools 的高级语法之LHS增强
  12. Tkinter教程之Label篇
  13. sshxcute_Java 使用SSH连接Linux 使用passwd命令修改密码
  14. 时间的思考---《把时间当作朋友》读后感
  15. Hibernate5自动建表坑之索引BUG(Cant DROP xxxxxxxxx check that column/key exists)
  16. Java下载安装及配置
  17. 人工智能发展简史——未来是属于AI人工智能的。
  18. php 中insert into,php – INSERT INTO SQL Heredoc正确的语法
  19. CAS单点登录(一)——初识SSO
  20. 耐人寻味的 for...else...语句

热门文章

  1. 检测、分割用什么轻量级网络呢?
  2. 目标检测 | 盘点目标检测中的特征融合技巧(根据YOLO v4总结)
  3. 详解OpenCV卷积滤波之边缘处理与锚定输出
  4. 新手必会的 9 个 Python 技巧!
  5. 【OpenCV 4开发详解】图像仿射变换
  6. bootstrap课程1 bootstrap为什么这么火
  7. SQL语句备份和还原数据库
  8. 编写一个程序,打印输入中各个字符出现频度的直方图
  9. [Head First设计模式]身边的设计模式——适配器模式
  10. 基于HTML5的WebGL结合Box2DJS物理应用