思路和任意模数FFT模板都来自 这里

看了一晚上那篇《再探快速傅里叶变换》还是懵得不行,可能水平还没到- -

只能先存个模板了,这题单模数NTT跑了5.9s,没敢写三模数NTT,可能姿势太差了...

具体推导大概这样就可以了:

/*
HDU 6088 - Rikka with Rock-paper-scissors [ 任意模数FFT,数论 ] | 2017 Multi-University Training Contest 5
题意:
计算 3^n * ∑ [0<=i+j<=n] C(n, i) * C(n-i, j) * GCD(i,j)
N <= 1e5
分析:
利用 n = ∑ [d|n] φ(d)
化得:
3^n * ∑[1<=d<=n] d ∑ [0<=i+j<=n/d] C(n,i*d) * C(n-i*d, j*d)
之后枚举 d (以下略写 *d )
C(n,i*d) * C(n-i*d, j*d)
= n! * 1/(i!) * 1/(j!) * 1/(n-i-j)!
维护 f(i) = 1/i! 的卷积 g(k) = ∑ [i+j == k] * f(i) * f(j)
原式 = ∑[1<=i<=m] n! * g(k) * 1/(n-k)!
由于 gcd(0, 0) == 0
所以特判卷积的 g(0) 项不用加上
*/
#include <bits/stdc++.h>
using namespace std;
#define MOD mod
#define upmo(a,b) (((a)=((a)+(b))%MOD)<0?(a)+=MOD:(a))
typedef long long LL;
typedef double db;
const int N = 1e5+5;
int t, n;
LL inv[N], F[N], Finv[N], phi[N];
LL MOD;
namespace FFT_MO
{
const int FFT_MAXN = 1<<18;
const db PI = 4*atan(1.0);
struct cp
{
db a, b;
cp(db a_ = 0, db b_ = 0) {
a = a_, b = b_;
}
cp operator + (const cp& rhs) const {
return cp(a+rhs.a, b+rhs.b);
}
cp operator - (const cp& rhs) const {
return cp(a-rhs.a, b-rhs.b);
}
cp operator * (const cp& rhs) const {
return cp(a*rhs.a-b*rhs.b, a*rhs.b + b*rhs.a);
}
cp operator !() const{
return cp(a, -b);
}
}nw[FFT_MAXN+1], f[FFT_MAXN], g[FFT_MAXN], t[FFT_MAXN];
int bitrev[FFT_MAXN];
void fft_init()
{
int L = 0; while ((1<<L) != FFT_MAXN) L++;
for (int i = 1; i < FFT_MAXN; i++)
bitrev[i] = bitrev[i>>1]>>1 | ((i&1)<<(L-1));
for (int i = 0; i <= FFT_MAXN; i++)
nw[i] = cp((db)cosl(2*PI/FFT_MAXN*i), (db)sinl(2*PI/FFT_MAXN*i));
}
void dft(cp *a, int n, int flag = 1)
{
int d = 0; while ((1<<d)*n != FFT_MAXN) d++;
for (int i = 0; i < n; i++) if (i < (bitrev[i]>>d))
swap(a[i], a[bitrev[i]>>d]);
for (int l = 2; l <= n; l <<= 1)
{
int del = FFT_MAXN/l*flag;
for (int i = 0; i < n; i += l)
{
cp *le = a+i, *ri = a+i+(l>>1);
cp *w = flag==1 ? nw : nw+FFT_MAXN;
for (int k = 0; k < (l>>1); k++)
{
cp ne = *ri * *w;
*ri = *le - ne, *le = *le+ne;
le++, ri++, w += del;
}
}
}
if (flag != 1) for (int i = 0; i < n; i++) a[i].a /= n, a[i].b /= n;
}
void convo(LL *a, int n, LL *b, int m, LL *c)
{
for (int i = 0; i <= n+m; i++) c[i] = 0;
int N = 2; while (N <= n+m) N <<= 1;
for (int i = 0; i < N; i++)
{
LL aa = i <= n ? a[i] : 0, bb = i <= m ? b[i] : 0;
aa %= MOD, bb %= MOD;
f[i] = cp(db(aa>>15), db(aa&32767));
g[i] = cp(db(bb>>15), db(bb&32767));
}
dft(f, N), dft(g, N);
for (int i = 0; i < N; i++)
{
int j = i ? N-i : 0;
t[i] = ((f[i]+!f[j])*(!g[j]-g[i]) + (!f[j]-f[i])*(g[i]+!g[j])) * cp(0, 0.25);
}
dft(t, N, -1);
for (int i = 0; i <= n+m; i++) upmo(c[i], (LL(t[i].a+0.5))%MOD<<15);
for (int i = 0; i < N; i++)
{
int j = i? N-i : 0;
t[i] = (!f[j]-f[i])*(!g[j]-g[i])*cp(-0.25,0) + cp(0,0.25)*(f[i]+!f[j])*(g[i]+!g[j]);
}
dft(t, N, -1);
for (int i = 0; i <= n+m; i++)
upmo(c[i], LL(t[i].a+0.5)+(LL(t[i].b+0.5)%MOD<<30));
}
}
LL a[1<<18|1], b[1<<18|1], c[1<<18|1];
LL PowMod(LL a, LL m)
{
a %= MOD;
LL ret = 1;
while (m) {
if (m&1) ret = ret * a % MOD;
m >>= 1;
a = a*a % MOD;
}
return ret;
}
void GetEuler()
{
memset(phi, 0, sizeof(phi));
phi[1] = 1;
for (int i = 2; i < N; i++)
if (!phi[i])
for (int j = i; j < N; j += i)
{
if (!phi[j]) phi[j] = j;
phi[j] = phi[j] / i * (i-1);
}
}
void init(int n) {
inv[1] = 1;
for (int i = 2; i <= n; i++)
inv[i] = (MOD - MOD/i) *inv[MOD % i] % MOD;
F[0] = Finv[0] = 1;
for (int i = 1; i <= n; i++) {
F[i] = F[i-1] * i % MOD;
Finv[i] = Finv[i-1] * inv[i] % MOD;
}
}
int main()
{
GetEuler();
scanf("%d", &t);
while (t--)
{
scanf("%d%lld", &n, &MOD);
init(n);
FFT_MO::fft_init();
LL ans = 0;
for (int d = 1; d <= n; d++)
{
int m = n/d;
for (int i = 0; i <= m; i++) b[i] = a[i] = Finv[i*d];
FFT_MO::convo(a, m, b, m, c);
for (int i = 0; i <= m; i++) c[i] = c[i] * Finv[n-i*d] % MOD;
LL sum = 0;
for (int i = 1; i <= m; i++) sum = (sum + c[i]) % MOD;
ans = (ans + sum * phi[d]) % MOD;
}
ans = ans * F[n] % MOD * PowMod(3, n) % MOD;
printf("%lld\n", ans);
}
}

  

HDU 6088 - Rikka with Rock-paper-scissors | 2017 Multi-University Training Contest 5的更多相关文章

  1. 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 H题 Rock Paper Scissors Lizard Spock.(FFT字符串匹配)

    2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...

  2. 2015多校联合训练赛 hdu 5308 I Wanna Become A 24-Point Master 2015 Multi-University Training Contest 2 构造题

    I Wanna Become A 24-Point Master Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 ...

  3. hdu 6088 Rikka with Rock-paper-scissors (2017 多校第五场 1004) 【组合数学 + 数论 + 模意义下的FFT】

    题目链接 首先利用组合数学知识,枚举两人的总胜场数容易得到 这还不是卷积的形式,直接搞的话复杂度大概是O(n^2)的,肯定会TLE.但似乎和卷积有点像?想半天没想出来..多谢Q巨提醒,才知道可以用下面 ...

  4. SDUT 3568 Rock Paper Scissors 状压统计

    就是改成把一个字符串改成三进制状压,然后分成前5位,后5位统计, 然后直接统计 f[i][j][k]代表,后5局状压为k的,前5局比和j状态比输了5局的有多少个人 复杂度是O(T*30000*25*m ...

  5. HDU 6088 Rikka with Rock-paper-scissors(NTT+欧拉函数)

    题意 \(n\) 局石头剪刀布,设每局的贡献为赢的次数与输的次数之 \(\gcd\) ,求期望贡献乘以 \(3^{2n}\) ,定义若 \(xy=0\) 则,\(\gcd(x,y)=x+y\) 思路 ...

  6. FFT(Rock Paper Scissors Gym - 101667H)

    题目链接:https://vjudge.net/problem/Gym-101667H 题目大意:首先给你两个字符串,R代表石头,P代表布,S代表剪刀,第一个字符串代表第一个人每一次出的类型,第二个字 ...

  7. Gym - 101667H - Rock Paper Scissors FFT 求区间相同个数

    Gym - 101667H:https://vjudge.net/problem/Gym-101667H 参考:https://blog.csdn.net/weixin_37517391/articl ...

  8. Gym101667 H. Rock Paper Scissors

    将第二个字符串改成能赢对方时对方的字符并倒序后,字符串匹配就是卷积的过程. 那么就枚举字符做三次卷积即可. #include <bits/stdc++.h> struct Complex ...

  9. 【题解】CF1426E Rock, Paper, Scissors

    题目戳我 \(\text{Solution:}\) 考虑第二问,赢的局数最小,即输和平的局数最多. 考虑网络流,\(1,2,3\)表示\(Alice\)选择的三种可能性,\(4,5,6\)同理. 它们 ...

随机推荐

  1. HanLP-地名识别调试方法

    HanLP收词特别是实体比较多,因此特别容易造成误识别.下边举几个地名误识别的例子,需要指出的是,后边的机构名识别也以地名识别为基础,因此,如果地名识别不准确,也会导致机构名识别不准确. 类型1 数字 ...

  2. 1、Ubuntu linux下同步windows火狐foxfire 浏览器收藏夹问题

    最近在ubuntu系统中使用自带的firefox浏览器,发现有一些问题,比如登陆后,书签,历史记录等,原本在windows下同步的数据无法同步,添加书签的功能也无法使用. 经过查询资料后得知,unbu ...

  3. 数据库学习其一 oracle11g数据泵导入导出

    一.检查环境一致性 需检查数据库客户端与服务端字符编码,以避免后续各种各样的问题 查询服务端编码 注意最好用sqlplus查询,用plsql有时候会出现查询不一致问题,如下图同一个语句在plsql和s ...

  4. elasticsearch进行远程访问,所面对的问题解决方案

    elasticsearch6.2进行远程访问,修改yml文件后,启动会报错: 上面四个问题解决方案如下: 问题1,问题2,问题3,解决如下: 注意: 针对第二个问题,你可能在limits.d目录中没有 ...

  5. Netty源码剖析-接受数据

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:worker thread ①多路复用器(Select ...

  6. (三)IDEA创建Spring项目

    新建项目的时候,选择Spring : 在Spring的下面,有许多选项,根据自己需求选择,我是初学,就一个都没有勾选: 选择 Web Application 选项 默认是下载Spring的jar包:如 ...

  7. 沿路径动画(Animation Along a Path)

    Silverlight 提供一个好的动画基础,但缺少一种方便的方法沿任意几何路径对象进行动画处理.在Windows Presentation Foundation中提供了动画处理类DoubleAnim ...

  8. 使用postman修改SAP Marketing Cloud contact主数据

    Marketing Cloud里的contact主数据,创建成功后也不是所有字段都能够被修改.在Personal data区域的字段是可以被修改的. 比如我在"客户属性"字段里维护 ...

  9. 【Mac】 开启原生的 NTFS 硬盘格式支持

    一.MacOS 10.13 之前 二.MacOS 10.13 及之后 一.MacOS 10.13 之前 直接跳到引用地址查看,下面的草记只是为了防止链接丢失 引用地址 打开终端 切换至root身份,输 ...

  10. 【Git】三、版本回退&撤消修改&文件删除

    提要 //查看git操作日志 $ git log //单行格式查看操作日志 $ git log --pretty=oneline //还原操作到上一次版本,有几个^就上几次 $ git reset - ...