zoukankan      html  css  js  c++  java
  • 【BZOJ】3771: Triple

    http://www.lydsy.com/JudgeOnline/problem.php?id=3771

    题意:n个带价值互不相同的物品,每次可以取1、2、3个物品,问能得到的所有的价值和这个价值的方案数(n不明(无意义= =),价值<=40000)

    #include <bits/stdc++.h>
    using namespace std;
    const int N=200005;
    int bit[N];
    const double PI=acos(-1);
    struct cp {
    	double r, i;
    	cp(double _r=0, double _i=0) : r(_r), i(_i) {}
    	cp operator + (const cp &a) { return cp(r+a.r, i+a.i); }
    	cp operator - (const cp &a) { return cp(r-a.r, i-a.i); }
    	cp operator * (const cp &a) { return cp(r*a.r-i*a.i, r*a.i+i*a.r); }
    };
    void dft(cp *a, int n, int flag) {
    	for(int i=0; i<n; ++i) if(i<bit[i]) swap(a[i], a[bit[i]]);
    	for(int m=2; m<=n; m<<=1) {
    		cp wn(cos(PI*2.0/m), sin(PI*2.0/m)*flag);
    		int mid=m>>1;
    		for(int i=0; i<n; i+=m) {
    			cp w(1);
    			for(int j=0; j<mid; ++j) {
    				static cp u, v;
    				u=a[i+j], v=a[i+j+mid]*w;
    				a[i+j]=u+v;
    				a[i+j+mid]=u-v;
    				w=w*wn;
    			}
    		}
    	}
    	if(flag==-1) for(int i=0; i<n; ++i) a[i].r/=n;
    }
    void fft(int *A, int *B, int *C, int n) {
    	static cp a[N], b[N];
    	int len=1, bitl=-1;
    	for(; len<n; len<<=1, ++bitl);
    	for(int i=0; i<len; ++i) bit[i]=(bit[i>>1]>>1)|((i&1)<<bitl);
    	for(int i=0; i<len; ++i) a[i].r=A[i], a[i].i=0, b[i].r=B[i], b[i].i=0;
    	dft(a, len, 1); dft(b, len, 1);
    	for(int i=0; i<len; ++i) b[i]=a[i]*b[i];
    	dft(b, len, -1);
    	for(int i=0; i<len; ++i) C[i]=b[i].r+0.5;
    }
    int a[N], b[N], c[N], t[N], ans[N], n, len;
    void work() {
    	int l=n;
    	for(int i=0; i<l; ++i) ans[i]=a[i];
    	fft(a, a, t, n*2-1);
    	l=n*2-1;
    	for(int i=0; i<l; ++i) ans[i]+=(t[i]-b[i])>>1;
    	fft(a, t, t, n*3-2);
    	fft(a, b, a, n*3-2);
    	l=n*3-2;
    	for(int i=0; i<l; ++i) ans[i]+=(t[i]-3*a[i]+(c[i]<<1))/6;
    }
    int main() {
    	scanf("%d", &len);
    	for(int i=0; i<len; ++i) { int x; scanf("%d", &x); a[x]=1; b[x*2]=1; c[x*3]=1; n=max(x+1, n); }
    	work();
    	len=n*3-2;
    	for(int i=0; i<len; ++i) if(ans[i]) printf("%d %d
    ", i, ans[i]);
    	return 0;
    }
    

      

    首先容易得到母函数$A=sum_{存在价值为i的物品} x^i$

    敲完了fft才发现如果直接求母函数的三次方是不对的= =...

    妈呀竟然没想到容斥QAQ

    设$B = {A[i]^2}, C = {A[i]^3}$

    首先我们对取法分别求:

    取1个的方案 $ = A$

    取2个的方案 $ = frac{A^2 - B}{A^{2}_{2}} = frac{A^2 - B}{2}$

    取3个的方案 $ = frac{A^3 - frac{3!}{2!1!} AB + frac{3!}{2!1!} C - C}{A^{3}_{3}} = frac{A^3 -3AB + 2C}{6}$

    (看不懂的建议先去看《组合数学》= =)

    然后fft搞搞就行辣= =

  • 相关阅读:
    史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka)
    漫谈《大型网站技术架构》
    如何使用MongoDB+Springboot实现分布式ID?
    IOS UIView 01-View开始深入 绘制像素到屏幕上
    IOS 多线程04-GCD详解 底层并发 API
    IOS 多线程05-OperationQueue 、GCD详解
    IOS 多线程02-pthread 、 NSThread 、GCD 、NSOperationQueue、NSRunLoop
    IOS 公共类-数字处理
    React Native02-开始运行 Android篇
    React Native01-开始 Windows环境安装配置篇
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4348290.html
Copyright © 2011-2022 走看看