博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ3771 Triple 【NTT + 容斥】
阅读量:4498 次
发布时间:2019-06-08

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

题目链接

题解

做水题放松一下

先构造\(A_i\)\(x\)指数的生成函数\(A(x)\)
再构造\(2A_i\)为指数的生成函数\(B(x)\)
再构造\(3A_i\)为指数的生成函数\(C(x)\)

那么只需计算

\[A(x) + \frac{A^2(x) - B(x)}{2} + \frac{A^{3}(x) - 3(A(x)B(x) - C(x))}{6}\]
那么\(x^i\)的系数即为损失价值\(i\)的方案数

#include
#include
#include
#include
#include
#include
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)#define REP(i,n) for (int i = 1; i <= (n); i++)#define mp(a,b) make_pair
(a,b)#define cls(s) memset(s,0,sizeof(s))#define cp pair
#define LL long long intusing namespace std;const int maxn = 800005,maxm = 100005,INF = 1000000000;inline int read(){ int out = 0,flag = 1; char c = getchar(); while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();} while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();} return out * flag;}const LL P = 2281701377ll,G = 3;inline LL qpow(LL a,LL b){ LL re = 1; for (; b; b >>= 1,a = a * a % P) if (b & 1) re = re * a % P; return re;}int R[maxn];inline void NTT(LL* a,int n,int f){ for (int i = 0; i < n; i++) if (i < R[i]) swap(a[i],a[R[i]]); for (int i = 1; i < n; i <<= 1){ LL gn = qpow(G,(P - 1) / (i << 1)); for (int j = 0; j < n; j += (i << 1)){ LL g = 1,x,y; for (int k = 0; k < i; k++,g = g * gn % P){ x = a[j + k],y = g * a[j + k + i] % P; a[j + k] = (x + y) % P,a[j + k + i] = ((x - y) % P + P) % P; } } } if (f == 1) return; LL nv = qpow(n,P - 2); reverse(a + 1,a + n); for (int i = 0; i < n; i++) a[i] = a[i] * nv % P;}LL A[maxn],B[maxn],C[maxn],D[maxn],ans[maxn],val[maxn],N,deg;int main(){ N = read(); REP(i,N){ val[i] = read(),ans[val[i]]++; A[val[i]] = 1; deg = max(deg,val[i]); } //2 int n = 1,m = deg << 1,L = 0; while (n <= m) n <<= 1,L++; for (int i = 1; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1)); NTT(A,n,1); for (int i = 0; i < n; i++) A[i] = A[i] * A[i] % P; NTT(A,n,-1); REP(i,N) A[val[i] << 1]--; for (int i = 0; i < n; i++) ans[i] += A[i] >> 1; //3 REP(i,N) B[val[i]] = 1; n = 1,m = deg * 3,L = 0; while (n <= m) n <<= 1,L++; for (int i = 1; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1)); NTT(B,n,1); for (int i = 0; i < n; i++) B[i] = B[i] * B[i] % P * B[i] % P; NTT(B,n,-1); //2 + 1 REP(i,N) C[val[i] + val[i]] = 1,D[val[i]] = 1; int nn = 1; L = 0,m = deg * 3; while (nn <= m) nn <<= 1,L++; for (int i = 1; i < nn; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1)); NTT(C,nn,1); NTT(D,nn,1); for (int i = 0; i < nn; i++) C[i] = C[i] * D[i] % P; NTT(C,nn,-1); REP(i,N) C[val[i] * 3]--; for (int i = 0; i < nn; i++) C[i] *= 3; for (int i = 0; i < n; i++) B[i] -= C[i],B[i] /= 6,ans[i] += B[i]; for (int i = 0; i <= deg * 3; i++) if (ans[i]) printf("%d %lld\n",i,ans[i]); return 0;}

转载于:https://www.cnblogs.com/Mychael/p/9193008.html

你可能感兴趣的文章
fenby C语言 P6
查看>>
分页查询
查看>>
【leetcode 简单】 第一百一十题 分发饼干
查看>>
解决python写入csv文件每两行间 隔一个空行的问题
查看>>
异常——获取异常信息
查看>>
JMeter学习-019-JMeter 监听器之【聚合报告】界面字段解析及计算方法概要说明(转载)...
查看>>
git 使用那些事儿
查看>>
Web测试
查看>>
Hadoop RPC源码阅读-客户端
查看>>
面试问答题及答案
查看>>
Ubuntu 14.10 下安装伪分布式hdoop 2.5.0
查看>>
Prometheus监控软件部署方法
查看>>
C+++string类如何判断字符串为空
查看>>
关于linux 添加新的硬盘
查看>>
【Java集合源码剖析】HashMap源码剖析
查看>>
openwrt固件支持3G和4G上网卡
查看>>
js2
查看>>
324. Wiggle Sort II
查看>>
129. Sum Root to Leaf Numbers
查看>>
Spark RDD详解
查看>>