zoukankan      html  css  js  c++  java
  • Bzoj3771 Triple

    Time Limit: 20 Sec  Memory Limit: 64 MB
    Submit: 563  Solved: 317

    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

    Source

    数学问题 生成函数 FFT 容斥

    题面挺带感的233

    设x[]为只拿一把斧头的方案构建的指数生成函数,y[]为拿了相同两把斧头的方案构建的指数生成函数,z[]为拿了相同三把斧头的方案构建的指数生成函数。

    那么可以容斥计算:

      拿一把的方案数:$O(n)$直接统计

      拿两把的方案数:$ans=(x*x-y)/2$

      拿三把的方案数: $ans= (x*x*x-3*x*y+2*z)/6 $

     1 /*by SilverN*/
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<vector>
     8 #define LL long long
     9 using namespace std;
    10 const double pi=acos(-1.0);
    11 const int mxn=160010;
    12 int read(){
    13     int x=0,f=1;char ch=getchar();
    14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    16     return x*f;
    17 }
    18 struct  com{
    19     double x,y;
    20     com operator + (com b){return (com){x+b.x,y+b.y};}
    21     com operator - (com b){return (com){x-b.x,y-b.y};}
    22     com operator * (com b){return (com){x*b.x-y*b.y,x*b.y+y*b.x};}
    23     com operator / (double v){return (com){x/v,y/v};}
    24 }a[mxn],b[mxn],c[mxn];
    25 int N,l,rev[mxn];
    26 void FFT(com *a,int flag){
    27     for(int i=0;i<N;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
    28     for(int i=1;i<N;i<<=1){
    29         com wn=(com){cos(pi/i),flag*sin(pi/i)};
    30         for(int j=0;j<N;j+=i<<1){
    31             com w=(com){1,0};
    32             for(int k=0;k<i;k++,w=w*wn){
    33                 com x=a[k+j],y=w*a[k+j+i];
    34                 a[k+j]=x+y;
    35                 a[k+j+i]=x-y;
    36             }
    37         }
    38     }
    39     if(flag==-1)for(int i=0;i<N;i++) a[i].x/=N;
    40     return;
    41 }
    42 int n,w[mxn];
    43 LL ans[mxn],d[mxn];
    44 int main(){
    45     int i,j,mx=0;
    46     n=read();
    47     for(i=1;i<=n;i++)w[i]=read(),mx=max(mx,w[i]);
    48     int m=mx*3;
    49     for(N=1;N<m;N<<=1)l++;
    50     for(i=0;i<=N;i++)
    51         rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    52     for(i=1;i<=n;i++){++ans[w[i]];}//只拿一把 
    53     //
    54     for(i=1;i<=n;i++)a[w[i]].x+=1;
    55     FFT(a,1);
    56     for(i=0;i<=N;i++)
    57         a[i]=a[i]*a[i];
    58     FFT(a,-1);
    59     for(i=0;i<=N;i++)d[i]+=(int)(a[i].x+0.3);
    60     for(i=1;i<=n;i++)d[w[i]+w[i]]--;
    61     for(i=0;i<=N;i++)ans[i]+=d[i]/2;
    62     //拿两把 
    63     memset(a,0,sizeof a);
    64     for(i=1;i<=n;i++)a[w[i]].x++;
    65     FFT(a,1);
    66     for(i=0;i<=N;i++) a[i]=a[i]*a[i]*a[i];
    67     FFT(a,-1);
    68     for(i=0;i<=N;i++)d[i]=(int)(a[i].x+0.3);
    69     memset(a,0,sizeof a);
    70     for(i=1;i<=n;i++){
    71         a[w[i]].x+=1;
    72         b[w[i]+w[i]].x+=1;
    73     }
    74     FFT(a,1);FFT(b,1);
    75     for(i=0;i<=N;i++)c[i]=a[i]*b[i];
    76     FFT(c,-1);
    77     for(i=0;i<=N;i++)d[i]-=((int)(c[i].x+0.3))*3;
    78     for(i=1;i<=n;i++){d[w[i]*3]+=2;}
    79     for(i=0;i<=N;i++)ans[i]+=d[i]/6;
    80     //拿三把 
    81     for(i=0;i<=N;i++)
    82         if(ans[i])
    83             printf("%d %lld
    ",i,ans[i]);
    84     return 0;
    85 }
  • 相关阅读:
    JVM简单入门
    10 张图聊聊线程的生命周期和常用 APIs
    Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Axios前后端分离模式下无感刷新实现JWT续期
    ueditor 插入视频代码解析
    CentOS下添加新硬盘并分区格式化的详细步骤
    Java 8 stream
    crontab命令详解
    计算机网络自顶向下学习杂记
    nginx安装
    js识别PC和H5
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6736854.html
Copyright © 2011-2022 走看看