zoukankan      html  css  js  c++  java
  • 【BZOJ3771】Triple 生成函数+FFT

    【BZOJ3771】Triple

    Description

    我们讲一个悲伤的故事。
    从前有一个贫穷的樵夫在河边砍柴。
    这时候河里出现了一个水神,夺过了他的斧头,说:
    “这把斧头,是不是你的?”
    樵夫一看:“是啊是啊!”
    水神把斧头扔在一边,又拿起一个东西问:
    “这把斧头,是不是你的?”
    樵夫看不清楚,但又怕真的是自己的斧头,只好又答:“是啊是啊!”
    水神又把手上的东西扔在一边,拿起第三个东西问:
    “这把斧头,是不是你的?”
    樵夫还是看不清楚,但是他觉得再这样下去他就没法砍柴了。
    于是他又一次答:“是啊是啊!真的是!”
    水神看着他,哈哈大笑道:
    “你看看你现在的样子,真是丑陋!”
    之后就消失了。
    樵夫觉得很坑爹,他今天不仅没有砍到柴,还丢了一把斧头给那个水神。
    于是他准备回家换一把斧头。
    回家之后他才发现真正坑爹的事情才刚开始。
    水神拿着的的确是他的斧头。
    但是不一定是他拿出去的那把,还有可能是水神不知道怎么偷偷从他家里拿走的。
    换句话说,水神可能拿走了他的一把,两把或者三把斧头。
    樵夫觉得今天真是倒霉透了,但不管怎么样日子还得过。
    他想统计他的损失。
    樵夫的每一把斧头都有一个价值,不同斧头的价值不同。总损失就是丢掉的斧头价值和。
    他想对于每个可能的总损失,计算有几种可能的方案。
    注意:如果水神拿走了两把斧头a和b,(a,b)和(b,a)视为一种方案。拿走三把斧头时,(a,b,c),(b,c,a),(c,a,b),(c,b,a),(b,a,c),(a,c,b)视为一种方案。

    Input

    第一行是整数N,表示有N把斧头。
    接下来n行升序输入N个数字Ai,表示每把斧头的价值。

    Output

    若干行,按升序对于所有可能的总损失输出一行x y,x为损失值,y为方案数。

    Sample Input

    4
    4
    5
    6
    7

    Sample Output

    4 1
    5 1
    6 1
    7 1
    9 1
    10 1
    11 2
    12 1
    13 1
    15 1
    16 1
    17 1
    18 1
    样例解释
    11有两种方案是4+7和5+6,其他损失值都有唯一方案,例如4=4,5=5,10=4+6,18=5+6+7.

    HINT

    所有数据满足:Ai<=40000

    题解:当年以为这就是个桶,后来得知这玩意叫生成函数。

    设所有斧头的生成函数为x,那么我们将x自乘1,2,3次,得到x,y,z,那么考虑每种情况被计算的次数。

    x——a:1次
    y——aa:1次,ab:2次
    z——aaa:1次,aab:3次,abc:6次

    那就把aa,aaa也求出来,用aa*b-aaa得到aab,就全统计出来了。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #define pi acos(-1.0)
    using namespace std;
    typedef long long ll;
    struct cp
    {
    	double x,y;
    	cp (double a,double b){x=a,y=b;}
    	cp (){}
    	cp operator + (cp a){return cp(x+a.x,y+a.y);}
    	cp operator - (cp a){return cp(x-a.x,y-a.y);}
    	cp operator * (cp a){return cp(x*a.x-y*a.y,x*a.y+y*a.x);}
    	cp operator * (double a){return cp(x*a,y*a);}
    }n1[1<<19],n2[1<<19],n3[1<<19];
    int n,m,top,len;
    int ans[1<<19];
    ll s[1<<19];
    void FFT(cp *a,int f)
    {
    	int i,j,k,h;
    	cp t;
    	for(i=k=0;i<len;i++)
    	{
    		if(i>k)	swap(a[i],a[k]);
    		for(j=(len>>1);(k^=j)<j;j>>=1);
    	}
    	for(h=2;h<=len;h<<=1)
    	{
    		cp wn(cos(f*2*pi/h),sin(f*2*pi/h));
    		for(j=0;j<len;j+=h)
    		{
    			cp w(1,0);
    			for(k=j;k<j+h/2;k++)	t=w*a[k+h/2],a[k+h/2]=a[k]-t,a[k]=a[k]+t,w=w*wn;
    		}
    	}
    }
    int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd();
    	int i,a;
    	for(i=1;i<=n;i++)	a=rd(),n1[a].x+=1,s[a]++,n2[a<<1].x+=1,n3[a*3].x+=1,m=max(m,a);
    	for(len=1;len<=m*3;len<<=1);
    	FFT(n1,1),FFT(n2,1),FFT(n3,1);
    	for(i=0;i<len;i++)
    	{
    		cp x=n1[i],y=n2[i],z=n3[i];
    		n2[i]=((x*x)-y)*(1.0/2),n3[i]=((x*x*x)-(x*y*3.0)+(z*2.0))*(1.0/6);
    	}
    	FFT(n2,-1),FFT(n3,-1);
    	for(i=0;i<len;i++)	s[i]+=(ll)(n2[i].x/len+0.1)+(ll)(n3[i].x/len+0.1);
    	for(i=0;i<len;i++)	if(s[i])	ans[++top]=i;
    	for(i=1;i<=top;i++)	printf("%d %lld
    ",ans[i],s[ans[i]]);
    	return 0;
    }
  • 相关阅读:
    子程序的设计
    多重循环程序设计
    汇编语言的分支程序设计与循环程序设计
    代码调试之串口调试2
    毕昇杯模块之光照强度传感器
    毕昇杯之温湿度采集模块
    【CSS】盒子模型 之 IE 与W3C的盒子模型对比
    【css】盒子模型 之 概述
    【css】盒子模型 之 弹性盒模型
    【网络】dns_probe_finished_nxdomain 错误
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7411502.html
Copyright © 2011-2022 走看看