整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


Weblink

https://ac.nowcoder.com/acm/contest/11253/J

Problem

ttt 组数据

给定一个集合 S,在 S 中找出元素个数为 kkk 的子集合 T ,计算 T 中所有元素的gcd⁡\gcdgcd,将所有的 T 得到的 gcd⁡\gcdgcd 乘在一起得到结果,结果对 P 取模。

t≤60,106≤P≤1014,1≤xi≤8⋅104,1≤∣S∣≤40000,1≤k≤min⁡(∣S∣,30)t\leq 60,10^6\leq P\leq 10^{14},1\leq x_i\leq 8\cdot 10^4,1\leq|S|\leq 40000,1\leq k\leq \min(|S|,30)t≤60,106≤P≤1014,1≤xi​≤8⋅104,1≤∣S∣≤40000,1≤k≤min(∣S∣,30)

Solution

统计 gcd⁡\gcdgcd 的乘积,显然无法正面去做,显然考虑从贡献的角度出发,枚举 gcd⁡\gcdgcd,我们只需要计算每个 gcd⁡\gcdgcd 出现多少次,乘起来就是答案。

显然一个集合 TTT 的 gcd⁡=d\gcd=dgcd=d,则集合 TTT 中元素均为 ddd 的倍数,且倍数互质。

因此我们可以倍数法 O(nlog⁡n)O(n\log n)O(nlogn) 预处理 f[i]f[i]f[i] 表示集合 SSS 中 iii 的倍数的数的个数。

显然从质因子出发容斥计算即可。

不动脑子的莫比乌斯反演做法:

∑d=1max⁡{xi}d∑T∈S[gcd⁡(T1d,T2d,⋯,Tkd)=1](modp)=∑d=1max⁡{xi}d∑T∈S∑i∣gcd⁡(T1d,⋯,Tkd)μ(i)(modp)=∑d=1max⁡{xi}d∑T∈S∑i=1⌊max⁡{xi}d⌋μ(i)[i∣T1d][i∣T2d]⋯[i∣Tkd](modp)=∑d=1max⁡{xi}d∑i=1⌊max⁡{xi}d⌋μ(i)(f[i×d]k)(modp)=∑d=1max⁡{xi}d∑i=1⌊max⁡{xi}d⌋μ(i)(f[i×d]k)(modφ(p))(modp)\begin{aligned}&\ \ \ \ \ \displaystyle \sum_{d = 1}^{\max\{x_i\}}d^{\ \ \displaystyle \sum_{T\in S}[\gcd(\frac {T_1} d,\frac {T_2} d,\cdots,\frac {T_k} d)=1]}\pmod p&\\&=\displaystyle \sum_{d = 1}^{\max\{x_i\}}d^{\ \ \displaystyle \sum_{T\in S}\sum_{i\mid \gcd(\frac {T_1} d,\cdots,\frac {T_k} d)} \mu(i) }\pmod p&\\&=\displaystyle \sum_{d = 1}^{\max\{x_i\}}d^{\ \ \displaystyle \sum_{T\in S}\sum_{i=1}^{\left\lfloor\frac {\max\{x_i\}} d\right\rfloor}\mu(i) [i\mid \frac {T_1} d][i\mid \frac {T_2} d]\cdots [i\mid \frac {T_k} d]}\pmod p&\\&=\displaystyle \sum_{d = 1}^{\max\{x_i\}}d^{\ \ \displaystyle \sum_{i=1}^{\left\lfloor\frac {\max\{x_i\}} d\right\rfloor}\mu(i) {f[i\times d] \choose k}}\pmod p&\\&=\displaystyle \sum_{d = 1}^{\max\{x_i\}}d^{\ \ \displaystyle \sum_{i=1}^{\left\lfloor\frac {\max\{x_i\}} d\right\rfloor}\mu(i) {f[i\times d] \choose k}\pmod {\varphi(p)}}\pmod p\end{aligned} ​     d=1∑max{xi​}​d  T∈S∑​[gcd(dT1​​,dT2​​,⋯,dTk​​)=1](modp)=d=1∑max{xi​}​d  T∈S∑​i∣gcd(dT1​​,⋯,dTk​​)∑​μ(i)(modp)=d=1∑max{xi​}​d  T∈S∑​i=1∑⌊dmax{xi​}​⌋​μ(i)[i∣dT1​​][i∣dT2​​]⋯[i∣dTk​​](modp)=d=1∑max{xi​}​d  i=1∑⌊dmax{xi​}​⌋​μ(i)(kf[i×d]​)(modp)=d=1∑max{xi​}​d  i=1∑⌊dmax{xi​}​⌋​μ(i)(kf[i×d]​)(modφ(p))(modp)​​

其中 [i∣T1d][i∣T2d]⋯[i∣Tkd][i\mid \cfrac {T_1} d][i\mid \cfrac {T_2} d]\cdots [i\mid \cfrac {T_k} d][i∣dT1​​][i∣dT2​​]⋯[i∣dTk​​] 说明集合 TTT 内的元素一定是 i×di\times di×d 的倍数,集合 SSS 中共有 f[i×d]f[i\times d]f[i×d] 个
i×di\times di×d 的倍数的元素,从中选出 kkk 个组成集合 TTT,共有 (f[i×d]k)\displaystyle {f[i\times d]}\choose k(kf[i×d]​) 种方案。

这个过程直接枚举仍然是 O(nlog⁡n)O(n\log n)O(nlogn) 的…然后快速幂 + 欧拉降幂计算 dxd^{\ x}d x ,复杂度瓶颈在这儿, O(nlog⁡φ(P))O(n\log \varphi(P))O(nlogφ(P))。

预处理相关信息,然后直接枚举即可,大概是 O(Tnlog⁡φ(P))≈O(220,800,000)O(Tn\log \varphi(P))≈O(220,800,000)O(Tnlogφ(P))≈O(220,800,000) 的复杂度。

1000ms 时限,使用 PR算法 质因数分解然后求 φ\varphiφ ,再加上各种卡常大法,能稳定在 680ms 左右 hhh

Code

#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 8e4 + 10;#define plus(a, b, c) (a + b > c ? a + b - c : a + b)
#define minus(a, b, c) (a - b < 0 ? a - b + c : a - b)template <typename T> inline void read(T& t) {int f = 0, c = getchar(); t = 0;while (!isdigit(c)) f |= c == '-', c = getchar();while (isdigit(c)) t = t * 10 + c - 48, c = getchar();if (f) t = -t;
}template <typename T> void print(T x) {if (x < 0) x = -x, putchar('-');if (x > 9) print(x / 10);putchar(x % 10 + 48);
}int n, m, s, t, k;
ll mod, phi;
ll factor[100], total;
ll C[N + 7][32];
int f[N];
int mu[N];
int a[] = {2, 3, 5, 7, 11};
int primes[N], cnt;
bool vis[N];ll gcd(ll a, ll b)
{return b ? gcd(b, a % b) : a;
}ll mul(ll a, ll b, ll mod) {return ((a * b - (long long)((long long)((long double)a / mod * b + 1e-3) * mod)) % mod + mod) % mod;
}ll qpow(ll a, ll b, ll mod)
{ll res = 1;while(b) {if(b & 1) res = mul(res, a, mod);a = mul(a, a, mod);b >>= 1;}return res;
}ll mul1(ll a, ll b) {return ((a * b - (long long)((long long)((long double)a / mod * b + 1e-3) * mod)) % mod + mod) % mod;
}ll qpow1(ll a, ll b)
{ll res = 1;while(b) {if(b & 1) res = mul1(res, a);a = mul1(a, a);b >>= 1;}return res;
}bool miller_rabin(ll n) {if (n == 1) return 0;for (int i = 0; i < 5; ++i) {if (n == a[i]) return 1;if (!(n % a[i])) return 0;}ll d = n - 1;while (!(d & 1)) d >>= 1;for (int i = 1; i <= 5; ++i) {ll a = rand() % (n - 2) + 2;bool tmp_k = false;ll tmp_d = d;ll tmp = qpow(a, tmp_d, n);if (tmp == 1) tmp_k = true;while (tmp != 1 && tmp != n - 1 && tmp_d != n - 1) {tmp = mul(tmp, tmp, n);tmp_d <<= 1;}if (tmp == n - 1)    tmp_k = true;if (!tmp_k)return 0;}return 1;
}ll pollard_rho(ll n) {for (int i = 0; i < 5; ++i) if (n % a[i] == 0) return a[i];ll x = rand(), y = x, t = 1, a = rand() % (n - 2) + 2;for (int k = 2; ; k <<= 1, y = x) {ll q = 1;for (int i = 1; i <= k; ++i) {x = (mul(x, x, n) + a) % n;q = mul(q, abs(x - y), n);if (!(i & N)) {t = gcd(q, n);if (t > 1) break;}}if (t > 1 || (t = gcd(q, n)) > 1) break;}return t;
}void find(ll x) {if (x == 1 || x <= 0) return;if (miller_rabin(x)) {factor[++total] = x;return;}ll p = x;while (p == x) p = pollard_rho(x);while (x % p == 0) x /= p;find(p);find(x);
}void pre_work(int n)
{mu[1] = 1;for (int i = 2; i <= n; ++ i) {if(vis[i] == 0) primes[ ++ cnt] = i, mu[i] = -1;for (int j = 1; j <= cnt && i * primes[j] <= n; ++ j) {vis[i * primes[j]] = 1;if(i % primes[j] == 0) break;mu[i * primes[j]] -= mu[i];}}
}int maxx;void solve()
{maxx = 0;memset(f, 0, sizeof f);read(n), read(k), read(mod);for (int i = 1; i <= n; ++ i) {int x;read(x);f[x] ++ ;maxx = max(maxx, x);}for (int i = 1; i <= N - 7; ++ i)for (int j = 2 * i; j <= N - 7; j += i)f[i] += f[j];total = 0;find(mod);phi = mod;for (int i = 1; i <= total; ++ i)phi = phi / factor[i] * (factor[i] - 1); C[0][0] = 1;for (int i = 0; i <= n; ++ i) {for (int j = 0; j <= min(i, k); ++ j) {if(j == 0 || j == i) C[i][j] = 1;else C[i][j] = plus(C[i - 1][j - 1], C[i - 1][j], phi);}}  ll ans = 1;for (int d = 2; d <= maxx; ++ d) {ll sum = 0;for (int i = 1; i <= maxx / d; ++ i) {if(mu[i] == 0) continue;sum = (mu[i] == 1) ? plus(sum, C[f[i * d]][k], phi) : minus(sum, C[f[i * d]][k], phi);}ans = mul1(ans, qpow1(d, sum)); }printf("%lld\n", ans);
}int main()
{pre_work(N - 5);scanf("%d", &t);while(t -- ) {solve();}return 0;
}

2021牛客暑期多校训练营(二) J. Product of GCDs 不动脑子的莫比乌斯反演做法(相关推荐

  1. 2021牛客暑期多校训练营1 赛后总结

    比赛名称: 2021牛客暑期多校训练营1 比赛时间: 2021年7月17日 12:00 - 17:00 比赛结果: 3/11 自我总结: 这场比赛应该算是这个假期的第二场团队赛了, 之前打过一个比较简 ...

  2. 2021牛客暑期多校训练营

    2021牛客暑期多校训练营1 A- Alice and Bob /* 博弈问题 两堆石头,每人每次从其中一堆拿k(k>0)个, 同时从另一堆拿s*k个(s>=0),不能进行操作的即失败 * ...

  3. 训练实录 | 2021牛客暑期多校训练营2

    2021牛客暑期多校训练营2 传送门 C - Draw Grids solved by oye. 00:22:07(+) 题意: 给n,m两个数,表示有n行点和m列点,已知每次只能连两个相邻的点(斜的 ...

  4. 2021牛客暑期多校训练营9

    2021牛客暑期多校训练营9 题号 题目 知识点 A A Math Challenge B Best Subgraph C Cells D Divide-and-conquer on Tree E E ...

  5. 2021牛客暑期多校训练营5

    2021牛客暑期多校训练营5 题号 题目 知识点 A Away from College B Boxes 概率 C Cheating and Stealing D Double Strings 线性d ...

  6. 2021牛客暑期多校训练营4

    2021牛客暑期多校训练营4 题号 题目 知识点 A Course B Sample Game C LCS D Rebuild Tree E Tree Xor 思维+线段树 F Just a joke ...

  7. 2021牛客暑期多校训练营3

    2021牛客暑期多校训练营3 题号 题目 知识点 A Guess and lies B Black and white C Minimum grid 二分图匹配 D Count E Math 数论+打 ...

  8. 2021牛客暑期多校训练营2

    2021牛客暑期多校训练营2 题号 题目 知识点 A Arithmetic Progression B Cannon C Draw Grids D Er Ba Game E Gas Station F ...

  9. 2021牛客暑期多校训练营1

    2021牛客暑期多校训练营1 题号 题目 知识点 难度 A Alice and Bob 博弈论 B Ball Dropping 计算几何 签到 C Cut the Tree D Determine t ...

最新文章

  1. 使用sublime text 执行 tcl 出错
  2. Extjs--FormPanel(2)
  3. IPSec ××× 在企业网中的应用
  4. 在同一页面显示多个JavaScript统计图表
  5. 【转载】通过金矿模型介绍动态规划 (动态规划入门)
  6. 手机电池余量 java,用Java获取电池电量
  7. 为socket的recv/send设置超时
  8. Tushare数据工具介绍
  9. matlab 矩阵转置
  10. 【最优化基础】惩罚和障碍函数
  11. 扣扣机器人唱歌_qq小冰机器人唱歌脚本-qq群机器人小冰无限唱歌插件下载v6.7.1 安卓版-腾牛安卓网...
  12. 微软企业邮箱邮箱服务器地址,微软Outlook添加网易企业邮箱设置步骤
  13. android之计时器chronometer
  14. sqlserver触发器Tigger使用及示例
  15. 编译tensorflow1.15.4,使其支持AVX2 和 FMA
  16. linux系统源码安装dosbox,Linux-dosbox使用
  17. undefined和“undefined”
  18. javaweb JSP JAVA 新闻发布系统源码(新闻管理系统)jsp新闻发布系统
  19. 计算机应用基础第三版答案,新版《计算机应用基础》各章课后习题-有答案.doc...
  20. 程序员编程的心灵鸡汤

热门文章

  1. 无人驾驶 | 为什么双目自动驾驶系统难以普及?
  2. 理解计算机视觉中的损失函数
  3. 面试题: 难点 已看1
  4. Ubuntu 16.04 LTS 常用工具软件整理(陆续更新)
  5. 在像Angular2这样的SPA应用中使用Google Analytics的方法
  6. python 对象拷贝
  7. php判断值是否为空
  8. Strategy模式
  9. scala报错20/08/31 23:48:40 WARN TaskSetManager: Lost task 1.0 in stage 0.0 (TID 1, 192.168.28.94, exec
  10. php提交字段打印,在隱藏的表單字段中提交的JSON編碼的PHP數組 - 在提交表單的頁面中打印時會產生奇怪的輸出...