博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 6088 - Rikka with Rock-paper-scissors | 2017 Multi-University Training Contest 5
阅读量:7242 次
发布时间:2019-06-29

本文共 4773 字,大约阅读时间需要 15 分钟。

思路和任意模数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 
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<
>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)) 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); }}

  

转载于:https://www.cnblogs.com/nicetomeetu/p/7354961.html

你可能感兴趣的文章
windows下 安装 rabbitMQ
查看>>
请谨慎使用sp_executesql
查看>>
练习- Tab切换效果
查看>>
windows下MySQL 5.7+ 解压缩版安装配置方法--转载
查看>>
C. Anya and Smartphone
查看>>
iOS—Xcode 7真机测试
查看>>
iOS开发——高级技术&本地化与国际化详解
查看>>
iOS开发UI篇—CALayer简介
查看>>
返回一个最大整数组的最大子数组的和
查看>>
访问FTP服务器方法
查看>>
剑指offer-面试题13.在O(1)时间删除链表节点
查看>>
Android MonkeyRunner自动拨打电话
查看>>
LeetCode OJ - Word Ladder 2
查看>>
天朝git的使用
查看>>
【java】java学习之路-03-MySQL(一)
查看>>
什么绑架了我们的注意力
查看>>
第五次团队作业——团队作业大汇总
查看>>
VBA 公式中使用相对位置
查看>>
架构之美阅读笔记之五
查看>>
发现大量的TIME_WAIT解决办法 -- 修改内核参数
查看>>