感觉我的做法并不是最优做法...

考虑一个置换\(g\)中的一个置换环\(S\)

在\(g^n\)的形态中,它变为了\(gcd(n, |S|)\)个长度相同的置换环

那么,我们考虑对\(f\)的所有置换环考虑

所有的长度相同的置换环都可以合并

如果\(a\)个长度为\(b\)的置换环合并成一个环,那么方案数为\(b^{a - 1} (a - 1)!\)

需要判掉不合法的情况

其意义是考虑第一个置换以及固定第一个元素,其他任意选择

以这个弄出指数生成函数\(F(x)\),那么对于长度为\(b\)的合并方案就是\(e^{F(x)} [num(b)]\)\

对于每个长度都这么讨论即可

复杂度\(O(n \log n)\)


#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; #define ll long long
#define ri register int
#define rec(io, ed) for(ri io = 0; io < ed; io ++)
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --) #define gc getchar
inline int read() {
int p = 0, w = 1; char c = gc();
while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
} const int sid = 3e5 + 5;
const int mod = 998244353; inline void inc(int &a, int b) { a += b; if(a >= mod) a -= mod; }
inline void dec(int &a, int b) { a -= b; if(a < 0) a += mod; }
inline int mul(int a, int b) { return 1ll * a * b % mod; }
inline int fp(int a, int k) {
int ret = 1;
for( ; k; k >>= 1, a = mul(a, a))
if(k & 1) ret = mul(ret, a);
return ret;
} int n, rev[sid];
int vis[sid], nc[sid], p[sid]; inline void init(int Mn, int &N, int &lg) {
N = 1, lg = 0;
while(N < Mn) N <<= 1, lg ++;
} inline void NTT(int *a, int n, int opt) {
rec(i, n) if(i < rev[i]) swap(a[i], a[rev[i]]);
for(ri i = 1; i < n; i <<= 1)
for(ri j = 0, g = fp(3, (mod - 1) / (i << 1)); j < n; j += (i << 1))
for(ri k = j, G = 1; k < i + j; k ++, G = mul(G, g)) {
int x = a[k], y = mul(G, a[i + k]);
a[k] = (x + y >= mod) ? x + y - mod : x + y;
a[i + k] = (x - y <0) ? x - y + mod : x - y;
}
if(opt == -1) {
reverse(a + 1, a + n);
int ivn = fp(n, mod - 2);
rec(i, n) a[i] = mul(a[i], ivn);
}
} int iva[sid], ivb[sid];
inline void Inv(int *a, int *b, int n) {
if(n == 1) { b[0] = fp(a[0], mod - 2); return; }
Inv(a, b, n >> 1);
int N = 1, lg = 0; init(n + n, N, lg);
rec(i, N) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
rec(i, N) iva[i] = ivb[i] = 0;
rec(i, n) iva[i] = a[i], ivb[i] = b[i];
NTT(iva, N, 1); NTT(ivb, N, 1);
rec(i, N) iva[i] = ((ivb[i] << 1) % mod - mul(iva[i], mul(ivb[i], ivb[i])) + mod) % mod;
NTT(iva, N, -1);
rec(i, n) b[i] = iva[i];
} int inv[sid], ivf[sid], fac[sid];
inline void pre() {
inv[0] = inv[1] = 1;
fac[0] = fac[1] = 1;
rep(i, 2, 200000) fac[i] = mul(fac[i - 1], i);
rep(i, 2, 200000) inv[i] = mul(inv[mod % i], mod - mod / i);
rep(i, 0, 200000) ivf[i] = fp(fac[i], mod - 2);
} inline void wf(int *a, int *b, int n) { for(ri i = 1; i < n; i ++) b[i - 1] = mul(a[i], i); }
inline void jf(int *a, int *b, int n) { for(ri i = 1; i < n; i ++) b[i] = mul(a[i - 1], inv[i]); } int ina[sid], inb[sid];
inline void In(int *a, int *b, int n) {
int N = 1, lg = 0; init(n + n, N, lg);
rec(i, N) ina[i] = inb[i] = 0;
wf(a, ina, n); Inv(a, inb, n);
rec(i, N) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
NTT(ina, N, 1); NTT(inb, N, 1);
rec(i, N) ina[i] = mul(ina[i], inb[i]);
NTT(ina, N, -1); jf(ina, b, n);
} int exa[sid], exb[sid];
inline void Exp(int *a, int *b, int n) {
if(n == 1) { b[0] = 1; return; }
Exp(a, b, n >> 1);
rec(i, n + n) exb[i] = exa[i] = 0;
In(b, exb, n);
int N = 1, lg = 0; init(n + n, N, lg);
rec(i, N) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
rec(i, n) exa[i] = b[i], exb[i] = (a[i] - exb[i] + mod) % mod; exb[0] ++;
NTT(exa, N, 1); NTT(exb, N, 1);
rec(i, N) exa[i] = mul(exa[i], exb[i]);
NTT(exa, N, -1);
rec(i, n) b[i] = exa[i];
} inline int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
} int f[sid], g[sid];
inline void wish() {
rep(i, 1, n) {
if(vis[i]) continue;
int L = 0;
for(ri t = i; !vis[t]; t = p[t]) vis[t] = 1, L ++;
nc[L] ++;
}
pre();
int ret = 1;
rep(i, 1, n) if(nc[i]) {
int v = nc[i];
rep(j, 0, v) f[j] = g[j] = 0;
rep(j, 0, v) {
if(gcd(j * i, n) != j) continue;
f[j] = mul(mul(fac[j - 1], fp(i, j - 1)), ivf[j]);
}
int N = 1;
while(N < v + 5) N <<= 1;
Exp(f, g, N);
ret = mul(ret, mul(g[v], fac[v]));
}
printf("%d\n", ret);
} int main() {
n = read();
rep(i, 1, n) p[i] = read();
wish();
return 0;
}

luoguP4709 信息传递 置换 + 多项式exp的更多相关文章

  1. 洛谷 - Sdchr 的邀请赛 T4 信息传递

    (乱搞艹爆正解系列) 对不起,由于博主太弱了,并不会正解的多项式exp(甚至多项式exp我都不会2333). 只能来说一说我是怎么乱搞的啦QWQ 首先这个题最关键的性质是: 一个在原置换 g 中长度为 ...

  2. tg2015 信息传递 (洛谷p2661)

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  3. [NOIP2015]信息传递

    [NOIP2015]信息传递[问题描述]有

  4. [NOIP2015] 提高组 洛谷P2661 信息传递

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  5. 使用postMesssage()实现跨域iframe页面间的信息传递----转载

    由于web同源策略的限制,当页面使用跨域iframe链接时,主页面与子页面是无法交互的,这对页面间的信息传递造成了不小的麻烦,经过一系列的尝试,最后我发现有以下方法可以实现: 1. 子页面url传参 ...

  6. 洛谷 P2661 信息传递 Label:并查集||强联通分量

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  7. NOIP 2015 信息传递

    kawayi 题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的 ...

  8. AC日记——信息传递 洛谷 P2661 (tarjan求环)

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  9. 2015 NOIP day2 t2 信息传递 tarjan

    信息传递 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.luogu.org/problem/show?pid=2661 Descrip ...

随机推荐

  1. 【Mysql sql inject】【入门篇】sqli-labs使用 part 4【18-20】

    这几关的注入点产生位置大多在HTTP头位置处 常见的HTTP注入点产生位置为[Referer].[X-Forwarded-For].[Cookie].[X-Real-IP].[Accept-Langu ...

  2. NandFlash和iNand

    nand 1.nand的单元组织:block与page(大页Nand与小页Nand)(1)Nand的页和以前讲过的块设备(尤其是硬盘)的扇区是类似的.扇区最早在磁盘中是512字节,后来也有些高级硬盘扇 ...

  3. 关注网页的更新状况,了解最新的handsup 消息.

    // 第一部分是网页截图和源码保存 // upon page load. var fs = require("fs"); var resourceWait = 300, maxRe ...

  4. jvm系列三、java GC算法 垃圾收集器

    原文链接:http://www.cnblogs.com/ityouknow/p/5614961.html 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 ...

  5. ASP.NET Core Identity 实战(3)认证过程

    如果你没接触过旧版Asp.Net Mvc中的 Authorize 或者 Cookie登陆,那么你一定会疑惑 认证这个名词,这太正式了,这到底代表这什么? 获取资源之前得先过两道关卡Authentica ...

  6. 使用Navicat Premium对mssql2008r2授权用户

    使用Navicat Premium操作mssql2008r2数据库 比如需要对某个特定的数据tes添加一个管理员em,并且这个管理员只能对test这个数据库进行操作 使用sa连接数据库 1.新建一个登 ...

  7. cacti系列(二)之cacti添加对tomcat服务器的监控

    cacti添加对tomcat的监控 1.首先下载监控tomcat的模板 TomcatStats-0.1.zip    2.导入模板 (cacti_host_template_tomcat_server ...

  8. 安装cactiez v11对windows和linux系统进行监控

    日常运维中我们需要对服务器的流量.CPU占用.硬盘使用及内存.磁盘IP等进行监控和了解,cactiez是一款基于centos6.4定制安装了常用监控软件的系统,安装简单,功能强大很适合快速部署监控系统 ...

  9. MariaDB:删除数据库报错:error: 'Error dropping database (can't rmdir './shiro', errno: 39)'

    今天在删除一个库的时候报错,如下图所示. 删除命名:mysqladmin –u root –p  drop shiro 解决办法: 删除./shiro目录下面的所有文件和目录. 重新执行删除命令即可!

  10. 10-关于DOM的事件操作

    一.JavaScript的组成 JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:文档对象 ...