传送门


先不考虑循环同构的限制,那么对于一个满足条件的序列,如果它的循环节长度为\(d\),那么与它同构的环在答案中就会贡献\(d\)次。

所以如果设\(f_i\)表示循环节长度恰好为\(i\)的满足条件的序列个数(不考虑循环同构),那么最后的答案就是\(\sum \frac{f_i}{i}\)。

所以问题变成了如何求\(f_i\)。注意到\(f_i\)直接求不是很好求,考虑计算\(cnt(\frac{n}{d} , \frac{m}{d})\)表示珠子数为\(\frac{n}{d}\)、黑色珠子数为\(\frac{m}{d}\)、不考虑循环同构的合法方案数,不难注意到\(\sum\limits_{i | d} f_i = cnt(\frac{n}{d} , \frac{m}{d})\)。所以只需要把所有\(cnt(\frac{n}{d} , \frac{m}{d})\)算出来然后莫比乌斯反演一下就可以得到所有\(f_i\)。

然后我们将原问题变成了不需要考虑循环同构的问题\(cnt(a,b)\)。

对于\(cnt(a,b)\),考虑\(a-b\)个白色球产生的\(a-b+1\)个区间,每一个区间内放入的黑色球的数量不能超过\(k\),且首尾放入的球的数量之和不能超过\(k\)。也就是要求\(\sum\limits_{i=0}^{a-b} x_i = b , \forall i , x_i \leq k , x_0 + x_{a-b} = k\)的满足条件的\(x\)序列的数量。不难得到这个序列的生成函数为\((\sum\limits_{i=0}^k x^i)^{a-b-1} (\sum\limits_{i=0}^k(i+1)x^i)\),我们要求的是它的\(x^b\)项系数。显然多项式快速幂不够优秀,考虑更快的方法。

由\(\sum\limits_{i=0}^k x_i = \frac{1 - x^{k+1}}{1 - x}\),可以得到

\((\sum\limits_{i=0}^k x^i)^{a - b - 1} = (1 - x^{k+1})^{a-b-1}(1 - x)^{-(a-b-1)}\)

\(\begin{align*}\sum\limits_{i=0}^k(i + 1)x^i &= \sum\limits_{i=0}^k \sum\limits_{j=i}^k x^i \\ &= \sum\limits_{i=0}^k\frac{x^i - x^{k+1}}{1 - x} \\ &= \frac{\sum\limits_{i=0}^k x^i - (k+1)x^{k+1}}{1-x} \\ &= \frac{\frac{1-x^{k+1}}{1-x} - (k+1)x^{k+1}}{1 - x} = \frac{1 - (k + 2)x^{k+1} + (k + 1)x^{k + 2}}{(1-x)^2} \end{align*}\)

所以生成函数可以变形为\((1 - x^{k+1})^{a-b-1}(1-x)^{-(a - b + 1)}(1 - (k + 2)x^{k+1} + (k+1)x^{k+2})\)

注意到最后的一部分多项式只有\(3\)项,意味着前面两项的卷积只有\(x^b,x^{b - k - 1} , x^{b-k-2}\)项会对\(x^b\)项系数产生贡献

而由二项式定理可知

\((1 - x^{k+1})^{a-b-1} = \sum\limits_{i=0}^{a-b-1} \binom{a-b-1}{i} (-1)^i x^{ki+i},(1 - x)^{-(a-b+1)} = \sum\limits_{i=0}^{+\infty} \binom{-(a-b+1)}{i}(-1)^i x^i = \sum\limits_{i=0}^{+\infty} \binom{a - b + i}{i}x^i\)

故设\(A = \sum\limits_{ki+i+j = b} \binom{a-b-1}{i} (-1)^i \binom{a-b+j}{j} , B = \sum\limits_{ki+i+j = b - k - 1} \binom{a-b-1}{i} (-1)^i \binom{a-b+j}{j} , C = \sum\limits_{ki+i+j = b - k - 2} \binom{a-b-1}{i} (-1)^i \binom{a-b+j}{j}\)

那么\(cnt(a,b) = A - (k + 2)B + (k+1)C\)。\(ABC\)的计算式子都可以通过枚举\(i\)做到\(\frac{b}{k+1}\)的复杂度,所以计算\(cnt(a,b)\)的总复杂度为\(\frac{\sigma(n)}{k + 1}\),其中\(\sigma(n)\)为\(n\)的约数和,近似\(n\ log\ logn\)。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. //This code is written by Itst
  5. using namespace std;
  6. #define int long long
  7. const int MAXN = 2e6 + 7 , MOD = 998244353;
  8. int prm[MAXN] , jc[MAXN] , inv[MAXN] , mu[MAXN] , ans[MAXN];
  9. int cnt , N , M , K;
  10. bool nprm[MAXN];
  11. inline int poww(int a , int b){
  12. int times = 1;
  13. while(b){
  14. if(b & 1) times = times * a % MOD;
  15. a = a * a % MOD;
  16. b >>= 1;
  17. }
  18. return times;
  19. }
  20. void init(){
  21. mu[1] = 1;
  22. for(int i = 2 ; i <= 1e6 ; ++i){
  23. if(!nprm[i]){
  24. prm[++cnt] = i;
  25. mu[i] = -1;
  26. }
  27. for(int j = 1 ; j <= cnt && prm[j] * i <= 1e6 ; ++j){
  28. nprm[prm[j] * i] = 0;
  29. if(i % prm[j] == 0) break;
  30. mu[i * prm[j]] = -1 * mu[i];
  31. }
  32. }
  33. jc[0] = 1;
  34. for(int i = 1 ; i <= 2e6 ; ++i)
  35. jc[i] = jc[i - 1] * i % MOD;
  36. inv[2000000] = poww(jc[2000000] , MOD - 2);
  37. for(int i = 1999999 ; i >= 0 ; --i)
  38. inv[i] = inv[i + 1] * (i + 1) % MOD;
  39. }
  40. int C(int b , int a){return b < a ? 0 : 1ll * jc[b] * inv[a] % MOD * inv[b - a] % MOD;}
  41. int calc(int A , int B){
  42. int sum1 = 0 , sum2 = 0 , sum3 = 0;
  43. for(int i = 0 ; (K + 1) * i <= B ; ++i){
  44. int j = B - (K + 1) * i;
  45. sum1 = (sum1 + (i & 1 ? -1 : 1) * C(A - B - 1 , i) * C(A - B + j , j) % MOD + MOD) % MOD;
  46. }
  47. for(int i = 0 ; (K + 1) * i <= B - K - 1 ; ++i){
  48. int j = B - K - 1 - (K + 1) * i;
  49. sum2 = (sum2 + (i & 1 ? -1 : 1) * C(A - B - 1 , i) * C(A - B + j , j) % MOD + MOD) % MOD;
  50. }
  51. for(int i = 0 ; (K + 1) * i <= B - K - 2 ; ++i){
  52. int j = B - K - 2 - (K + 1) * i;
  53. sum3 = (sum3 + (i & 1 ? -1 : 1) * C(A - B - 1 , i) * C(A - B + j , j) % MOD + MOD) % MOD;
  54. }
  55. return (sum1 - (K + 2) * sum2 % MOD + (K + 1) * sum3 + MOD) % MOD;
  56. }
  57. signed main(){
  58. #ifndef ONLINE_JUDGE
  59. freopen("gift.in","r",stdin);
  60. freopen("gift.out","w",stdout);
  61. #endif
  62. init();
  63. ios::sync_with_stdio(0);
  64. cin >> N >> M >> K;
  65. if(M == 0){puts("1"); return 0;}
  66. for(int i = 1 ; i <= M ; ++i)
  67. ans[N / i] = M % i == 0 && N % i == 0 ? calc(N / i , M / i) : 0;
  68. for(int i = 1 ; i <= N ; ++i)
  69. if(N % i == 0 && M % (N / i) == 0)
  70. for(int j = 2 ; j * i <= N ; ++j)
  71. ans[i * j] = (ans[i * j] + ans[i] * mu[j] + MOD) % MOD;
  72. int sum = 0;
  73. for(int i = 1 ; i <= N ; ++i)
  74. if(N % i == 0 && M % (N / i) == 0)
  75. sum = (sum + poww(i , MOD - 2) * ans[i]) % MOD;
  76. cout << sum << '\n';
  77. return 0;
  78. }

Luogu4916 魔力环 莫比乌斯反演、组合、生成函数的更多相关文章

  1. 【51nod】1222 最小公倍数计数 莫比乌斯反演+组合计数

    [题意]给定a和b,求满足a<=lcm(x,y)<=b && x<y的数对(x,y)个数.a,b<=10^11. [算法]莫比乌斯反演+组合计数 [题解]★具体 ...

  2. LOJ6519. 魔力环(莫比乌斯反演+生成函数)

    题目链接 https://loj.ac/problem/6519 题解 这里给出的解法基于莫比乌斯反演.可以用群论计数的相关方法代替莫比乌斯反演,但两种方法的核心部分是一样的. 环计数的常见套路就是将 ...

  3. [jzoj 6084] [GDOI2019模拟2019.3.25] 礼物 [luogu 4916] 魔力环 解题报告(莫比乌斯反演+生成函数)

    题目链接: https://jzoj.net/senior/#main/show/6084 https://www.luogu.org/problemnew/show/P4916 题目: 题解: 注: ...

  4. bzoj 2440 简单莫比乌斯反演

    题目大意: 找第k个非平方数,平方数定义为一个数存在一个因子可以用某个数的平方来表示 这里首先需要考虑到二分才可以接下来做 二分去查找[1 , x]区间内非平方数的个数,后面就是简单的莫比乌斯反演了 ...

  5. hdu 1695 GCD 莫比乌斯反演入门

    GCD 题意:输入5个数a,b,c,d,k;(a = c = 1, 0 < b,d,k <= 100000);问有多少对a <= p <= b, c <= q <= ...

  6. 洛谷P3307 [SDOI2013]项链 [polya定理,莫比乌斯反演]

    传送门 思路 很明显的一个思路:先搞出有多少种珠子,再求有多少种项链. 珠子 考虑这个式子: \[ S3=\sum_{i=1}^a \sum_{j=1}^a\sum_{k=1}^a [\gcd(i,j ...

  7. Coprime (单色三角形+莫比乌斯反演(数论容斥))

    这道题,先说一下单色三角形吧,推荐一篇noip的论文<国家集训队2003论文集许智磊> 链接:https://wenku.baidu.com/view/e87725c52cc58bd631 ...

  8. HDU 5321 Beautiful Set (莫比乌斯反演 + 逆元 + 组合数学)

    题意:给定一个 n 个数的集合,然后让你求两个值, 1.是将这个集合的数进行全排列后的每个区间的gcd之和. 2.是求这个集合的所有的子集的gcd乘以子集大小的和. 析:对于先求出len,len[i] ...

  9. BZOJ 3309 莫比乌斯反演

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3309 题意:定义f(n)为n所含质因子的最大幂指数,求 $Ans=\sum _{i=1} ...

随机推荐

  1. Brute-forced Euclid Distance Transform

    Sepearable 2D EDT, going to extend to 3D in order to calculate the Signed Distance Function(Field) C ...

  2. 浅析C/C++中的switch/case陷阱

    浅析C/C++中的switch/case陷阱 先看下面一段代码: 文件main.cpp #include<iostream> using namespace std; int main(i ...

  3. javascript的隐式类型转换

    首先简单了解js的typeof,会返回六种类型 即 number string boolen function object undefined 也就是六种基本数据类型 显示类型转换大概有以下几种: ...

  4. Linux 防火墙

    目录 iptables配置 1. iptables 控制类型 2. 链表规则 3. iptables表 CentOS和RedHat 6.x CentOS和RedHat 7.x ufw ubuntu u ...

  5. Sql Full-Text Filter

    SQL Server 全文索引介绍(转载) 概述 全文引擎使用全文索引中的信息来编译可快速搜索表中的特定词或词组的全文查询.全文索引将有关重要的词及其位置的信息存储在数据库表的一列或多列中.全文索引是 ...

  6. Linux进程上下文切换过程context_switch详解--Linux进程的管理与调度(二十一)

    1 前景回顾 1.1 Linux的调度器组成 2个调度器 可以用两种方法来激活调度 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测 ...

  7. Unity的AssetDatabase路径格式

    开发环境 windows 7 Unity 5.3 及更高版本 前言 使用AssetDatabase.Load或AnimatorController.CreateAnimatorControllerAt ...

  8. 关于svn上传.classpath等问题

    1. svn版本:客户端版本与服务器版本 要尽量适配. 2. svn管理项目:有人将.classpath, .project, .mymetadata, .myumldata等文件也纳入到版本控制,如 ...

  9. 第十四届智能车培训 PLL锁相环

    什么是锁相环? PLL(Phase Locked Loop): 为锁相回路或锁相环,用来统一整合时脉讯号,使高频器件正常工作,如内存的存取资料等.PLL用于振荡器中的反馈技术. 许多电子设备要正常工作 ...

  10. 如何设置可以避免php代码中的中文在浏览器中成为乱码?

    其实很简单,只需要在代码开始的前面加上一条这样的语句就行: //这里面我的浏览器中的字符编码格式为utf-8,所以这里我设置为utf-8,如果你的浏览器中的默认编码不是这个,请选择浏览器默认的编码格式 ...