Description:


题解:


这种东西肯定是burnside引理:

\(\sum置换后不动点数 \over |置换数|\)

一般来说,是枚举置换\(i\),则\(对所有x,满足a[x+i]=a[i]\),然后a还要满足题目条件,但是仔细想一想,设\(d=gcd(i,n)\),只要a[0..d-1]满足就好了,所以:

\(Ans=\sum_{d|n}f(d)*\phi(n/d),f(d)表示\)不考虑循环同构时的答案。

然后考虑dp:

枚举0这一列的块是什么,然后设\(dp[i][1..4][1..4][1..3][1..3]\),表示确定了后\(i\)列,第一行的颜色,和长度,第二行的颜色和长度,1、2表示第0列的颜色, 3、4表示不同于1、2列的颜色。

然后暴写dp,我死了……

n<=3的时候要特判,那么n更大的时候要矩阵乘法。

事实上有矩阵乘法的做法可以改成BM,最短递推式大概不超过35项

Code:

  1. #include<bits/stdc++.h>
  2. #define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
  3. #define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
  4. #define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
  5. #define ll long long
  6. #define pp printf
  7. #define hh pp("\n")
  8. using namespace std;
  9. const int mo = 1e9 + 7;
  10. ll ksm(ll x, ll y) {
  11. ll s = 1;
  12. for(; y; y /= 2, x = x * x % mo)
  13. if(y & 1) s = s * x % mo;
  14. return s;
  15. }
  16. namespace cz {
  17. ll a[7] = {0, 0, 0, 24, 312, 1320, 3720};
  18. ll cz(ll x) {
  19. if(x <= 6) return a[x];
  20. ll s = 0;
  21. fo(i, 0, 6) {
  22. ll xs = 1;
  23. fo(j, 0, 6) if(i != j) xs = xs * (x - j) % mo * ksm(i - j, mo - 2) % mo;
  24. s += xs * a[i];
  25. }
  26. return s % mo;
  27. }
  28. }
  29. const int N = 200;
  30. ll num, n, k, a[N];
  31. ll f[N][5][5][4][4];
  32. ll dp(int n, int cnt, int a0, int a1, int b0, int b1) {
  33. ll m = k - cnt;
  34. memset(f, 0, sizeof f);
  35. f[n][1][cnt][a0][b0] = 1;
  36. fd(i, n, 1) {
  37. int c0 = 0, c1 = 0, c3 = 0, c4 = 0;
  38. if(i - 1 < a0 || i - 1 >= n - a1) c0 = 1;
  39. if(i - 1 < b0 || i - 1 >= n - b1) c1 = cnt;
  40. if(i - 1 == a0 || i - 1 == n - a1 - 1) c3 = 1;
  41. if(i - 1 == b0 || i - 1 == n - b1 - 1) c4 = cnt;
  42. fo(x, 1, 4) fo(y, 1, 4) fo(lx, 1, 3) fo(ly, 1, 3) if(f[i][x][y][lx][ly]) {
  43. ll F = f[i][x][y][lx][ly] % mo;
  44. fo(u, 1, 3) {
  45. ll xs = 1;
  46. if(c0 && u != c0) xs = 0;
  47. if(c1 && u != c1) xs = 0;
  48. if(c3 && u == c3) xs = 0;
  49. if(c4 && u == c4) xs = 0;
  50. if(u == 2 && cnt == 1) xs = 0;
  51. if(u <= 2 && (x == u || y == u)) xs = 0;
  52. if(!xs) continue;
  53. if(u == 3) {
  54. xs *= m;
  55. if(x >= 3) xs --;
  56. if(y >= 3) xs --;
  57. if(x == 3 && y == 3) xs ++;
  58. }
  59. xs = max(xs, 0ll);
  60. f[i - 1][u][u][1][1] += xs * F % mo;
  61. }
  62. fo(u, 1, 3) fo(v, 1, 4) if(u != v && v != 3) {
  63. ll xs = 1;
  64. if(c0 && u != c0) xs = 0;
  65. if(c1 && v != c1) xs = 0;
  66. if(c3 && u == c3) xs = 0;
  67. if(c4 && v == c4) xs = 0;
  68. if((u == 2 || v == 2) && cnt == 1) xs = 0;
  69. if(!xs) continue;
  70. fo(r1, 0, 1) fo(r2, 0, 1) {
  71. if(r1 && (u != x || lx == 3)) continue;
  72. if(r2 && (v != y || ly == 3)) continue;
  73. if(!r1 && u <= 2 && u == x) continue;
  74. if(!r2 && v <= 2 && v == y) continue;
  75. if(!r1 && !r2 && x != y) continue;
  76. if(x == y && (r1 || r2)) continue;
  77. int nlx = r1 ? lx + 1 : 1, nly = r2 ? ly + 1 : 1;
  78. xs = 1;
  79. if(u <= 2 || v <= 2 || r1 || r2) {
  80. if(r1 && r2) {
  81. xs = x != y;
  82. } else
  83. if(!r1 && !r2) {
  84. xs *= (u <= 2 || r1) ? 1 : (m - (x >= 3));
  85. xs *= (v <= 2 || r2) ? 1 : (m - (y >= 3));
  86. } else {
  87. if(r2) {
  88. xs *= (u <= 2) ? 1 : (m - (x >= 3) - (y >= 3 && v >= 3));
  89. } else {
  90. xs *= (v <= 2) ? 1 : (m - (x >= 3 && u >= 3) - (y >= 3));
  91. }
  92. }
  93. } else {
  94. if(x <= 2 && y <= 2) xs *= m * (m - 1); else
  95. if(x > 2 && y > 2) {
  96. if(x == y) xs *= (m > 2) ? (m - 1) * (m - 2) : 0; else
  97. xs *= (m > 3) ? (m - 2) * (m - 3) : 0;
  98. } else {
  99. xs *= (m > 1) ? (m - 1) * (m - 1) : 0;
  100. }
  101. }
  102. xs = max(xs, 0ll);
  103. xs %= mo;
  104. f[i - 1][u][v][nlx][nly] += xs * F % mo;
  105. }
  106. }
  107. }
  108. }
  109. ll ans = 0;
  110. fo(x, 1, 4) fo(y, 1, 4) fo(lx, 1, 3) fo(ly, 1, 3) if(f[0][x][y][lx][ly]) {
  111. ans = (ans + f[0][x][y][lx][ly]) % mo;
  112. }
  113. return ans;
  114. }
  115. void dp() {
  116. for(int n = 4; n <= 70; n ++) {
  117. a[n] = dp(n, 1, 1, 0, 1, 0) * k % mo;
  118. fo(i, 1, 3) fo(j, 1, i) fo(u, 1, 3) fo(v, 1, u)
  119. a[n] += dp(n, 2, j, i - j, v, u - v) * k % mo * (k - 1) % mo;
  120. a[n] %= mo;
  121. }
  122. // pp("%lld\n", a[5]);
  123. a[1] = 0;
  124. a[2] = (k * (k - 1) + k * (k - 1) % mo * (k - 2) * 2) % mo;
  125. a[3] = cz :: cz(k);
  126. }
  127. int m; ll b[N];
  128. namespace bm {
  129. ll f[3][N], len[3], fail[3], delta[3];
  130. void cp(int x, int y) {
  131. fo(i, 1, len[x]) f[y][i] = f[x][i];
  132. len[y] = len[x]; fail[y] = fail[x]; delta[y] = delta[x];
  133. }
  134. void solve(ll *a, int n) {
  135. fo(i, 1, n) f[0][i] = 0; len[0] = 0;
  136. fo(i, 1, n) {
  137. ll tmp = a[i];
  138. fo(j, 1, len[0]) tmp -= f[0][j] * a[i - j] % mo;
  139. tmp = (tmp % mo + mo) % mo;
  140. delta[0] = tmp;
  141. if(!tmp) continue;
  142. fail[0] = i;
  143. if(!len[0]) {
  144. cp(0, 1); f[0][len[0] = 1] = 0;
  145. continue;
  146. }
  147. cp(0, 2);
  148. ll mul = delta[0] * ksm(delta[1], mo - 2) % mo;
  149. int st = i - fail[1]; len[0] = max(len[0], st + len[1]);
  150. f[0][st] = (f[0][st] + mul) % mo;
  151. fo(j, 1, len[1]) f[0][st + j] = (f[0][st + j] + (mo - mul) * f[1][j]) % mo;
  152. if(len[2] - fail[2] < len[1] - fail[1]) cp(2, 1);
  153. }
  154. m = len[0] + 1; b[m] = 1;
  155. fo(i, 1, len[0]) b[i] = -f[0][m - i];
  156. }
  157. }
  158. ll c[N * 2], d[N * 2], e[N * 2];
  159. void qmo(ll *a) {
  160. fo(i, 0, 2 * m) a[i] %= mo;
  161. fd(i, 2 * m, m) if(a[i]) {
  162. ll v = a[i]; int c = i - m;
  163. fo(j, 1, m) a[c + j] = (a[c + j] - v * b[j]) % mo;
  164. }
  165. }
  166. ll solve(int n) {
  167. if(n <= 35) return a[n];
  168. fo(i, 0, 2 * m) c[i] = d[i] = 0;
  169. c[0] = 1; d[1] = 1;
  170. int y = n;
  171. for(; y; y /= 2) {
  172. if(y & 1) {
  173. fo(i, 0, 2 * m) e[i] = c[i], c[i] = 0;
  174. fo(i, 0, m) fo(j, 0, m) c[i + j] += e[i] * d[j] % mo;
  175. qmo(c);
  176. }
  177. fo(i, 0, 2 * m) e[i] = d[i], d[i] = 0;
  178. fo(i, 0, m) fo(j, 0, m) d[i + j] += e[i] * e[j] % mo;
  179. qmo(d);
  180. }
  181. ll ans = 0;
  182. fo(i, 1, m - 1) ans += c[i] * a[i] % mo;
  183. return ans % mo;
  184. }
  185. ll phi(int n) {
  186. ll s = n;
  187. for(int i = 2; i * i <= n; i ++) if(n % i == 0) {
  188. s = s / i * (i - 1);
  189. for(; n % i == 0; n /= i);
  190. }
  191. if(n > 1) s = s / n * (n - 1);
  192. return s;
  193. }
  194. int main() {
  195. freopen("experience.in", "r", stdin);
  196. freopen("experience.out", "w", stdout);
  197. scanf("%lld %lld %lld", &num, &n, &k);
  198. dp();
  199. bm :: solve(a, 70);
  200. ll ans = 0;
  201. for(int d = 1; d * d <= n; d ++) if(n % d == 0) {
  202. ans += solve(d) * phi(n / d) % mo;
  203. if(d != n / d) ans += solve(n / d) * phi(d) % mo;
  204. }
  205. ans = (ans % mo + mo) % mo * ksm(n, mo - 2) % mo;
  206. pp("%lld\n", ans);
  207. }

【NOI2019模拟2019.7.4】朝夕相处 (动态规划+BM)的更多相关文章

  1. 【NOI2019模拟2019.7.1】为了部落 (生成森林计数,动态规划)

    Description: \(1<=n<=1e9,1<=m,k<=100\) 模数不是质数. 题解: 先选m个点,最后答案乘上\(C_{n}^m\). 不妨枚举m个点的度数和D ...

  2. [JZOJ6247]【NOI2019模拟2019.6.27】C【计数】

    Description n<=200000 Solution 比赛时没做出这道题真的太弟弟了 首先我们从小到大插入数i,考虑B中有多少个区间的最大值为i 恰好出现的次数不太好计算,我们考虑计算最 ...

  3. [JZOJ6244]【NOI2019模拟2019.7.1】islands【计数】【图论】

    Description n<=1e9,M,K<=100 Solution 显然任选m个港口的答案是一样的,乘个组合数即可. 考虑枚举m个港口的度数之和D 可以DP计算 记\(F_{m,D} ...

  4. [JZOJ6244]【NOI2019模拟2019.7.1】Trominoes 【计数】

    Description n,m<=10000 Solution 考虑暴力轮廓线DP,按顺序放骨牌 显然轮廓线长度为N+M 轮廓线也是单调的 1表示向上,0表示向右 N个1,M个0 只能放四种骨牌 ...

  5. [JZOJ6241]【NOI2019模拟2019.6.29】字符串【数据结构】【字符串】

    Description 给出一个长为n的字符串\(S\)和一个长为n的序列\(a\) 定义一个函数\(f(l,r)\)表示子串\(S[l..r]\)的任意两个后缀的最长公共前缀的最大值. 现在有q组询 ...

  6. 【NOI2019模拟2019.6.29】字符串(SA|SAM+主席树)

    Description: 1<=n<=5e4 题解: 考虑\(f\)这个东西应该是怎样算的? 不妨建出SA,然后按height从大到小启发式合并,显然只有相邻的才可能成为最优答案.这样的只 ...

  7. 【NOI2019模拟2019.6.29】组合数(Lucas定理、数位dp)

    Description: p<=10且p是质数,n<=7,l,r<=1e18 题解: Lucas定理: \(C_{n}^m=C_{n~mod~p}^{m~mod~p}*C_{n/p} ...

  8. 【NOI2019模拟2019.6.27】B (生成函数+整数划分dp|多项式exp)

    Description: \(1<=n,k<=1e5,mod~1e9+7\) 题解: 考虑最经典的排列dp,每次插入第\(i\)大的数,那么可以增加的逆序对个数是\(0-i-1\). 不难 ...

  9. 【NOI2019模拟2019.7.1】三格骨牌(轮廓线dp转杨图上钩子定理)

    Description \(n,m<=1e4,mod ~1e9+7\) 题解: 显然右边那个图形只有旋转90°和270°后才能放置. 先考虑一个暴力的轮廓线dp: 假设已经放了编号前i的骨牌,那 ...

随机推荐

  1. 笔记63 Spring Boot快速入门(三)

    SpringBoot中使用JSP Springboot的默认视图支持是Thymeleaf,但是Thymeleaf还没开始学,熟悉的还是jsp,所以要让Springboot支持 jsp. 一.在pom. ...

  2. Java中实现线程通信的三个方法的作用是什么?

    Java提供了3个方法解决线程之间的通信问题,均是java.lang.Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常. 方法名 作 用 final void wait() ...

  3. 将中国标准时间)转化为yyyy-MM-dd

    有两种方法: 1. ]); ) + '-' + d.getDate() + ' ' + d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds ...

  4. express 路由能力

    demo var express=require("express"); var app=express(); app.get("/",function(req ...

  5. win10配置jdk环境变量及遇到的坑

    第一步.在系统变量中新增变量命名JAVA_HOME,值为jdk的安装目录 JAVA_HOME C:\Program Files\Java\jdk1.8.0_231 第二步.在系统变量中增加path的值 ...

  6. 特种设备TSG 认证流程

    特种设备许可,也叫安全注册(原为AZ安全注册认可),现为TS.国家为了防止和减少事故,保障人民群众生命和财产安全,促进经济发展而强制实施的安全监察.它的作用相当于欧盟的“CE”认证,但比“CE”认证更 ...

  7. webpack引入全局jQuery

    1.使用命令行npm install jquery来安装jQuery 2.在webpack.config.js文件里配置: plugins:[ new webpack.ProvidePlugin({ ...

  8. vma

    linux内核的每一样技术,都是为了解决某个问题的. vma结构体的提出是为了管理"虚拟内存空间"这个资源. 像brk(),mmap()分配给用户空间的都是虚拟地址(当然),那内核就要知道哪一部分虚拟 ...

  9. 用记事本和Eclipse编写Java程序

    JRE(Java Runtime Environment    Java运行环境) 包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一 ...

  10. Kubernetes重大漏洞?阿里云已第一时间全面修复

    近日,Kubernetes社区发现安全漏洞 CVE-2018-1002105,阿里云容器服务已在第一时间完成全面修复,敬请广大用户登录阿里云控制台升级Kubernetes版本. 目前Kubernete ...