zoukankan      html  css  js  c++  java
  • HDU5307 He is Flying

    JRY wants to drag racing along a long road. There are nn sections on the road, the ii-th section has a non-negative integer length sisi. JRY will choose some continuous sections to race (at an unbelievable speed), so there are totally n(n+1)2n(n+1)2 different ways for him to ride. If JRY rides across from the ii-th section to the jj-th section, he would gain ji+1j−i+1 pleasure. Now JRY wants to know, if he tries all the ways whose length is ss, what's the total pleasure he can get. Please be aware that in the problem, the length of one section could be zero, which means that the length is so trivial that we can regard it as 00.

    InputThe first line of the input is a single integer T (T=5)T (T=5), indicating the number of testcases. 

    For each testcase, the first line contains one integer nn. The second line contains nnnon-negative integers, which mean the length of every section. If we denote the total length of all the sections as ss, we can guarantee that 0s500000≤s≤50000 and 1n1000001≤n≤100000. 
    OutputFor each testcase, print s+1s+1 lines. The single number in the ii-th line indicates the total pleasure JRY can get if he races all the ways of length i1i−1. 
    Sample Input

    2
    3
    1 2 3
    4
    0 1 2 3

    Sample Output

    0
    1
    1
    3
    0
    2
    3
    1
    3
    1
    6
    0
    2
    7

    数学问题 生成函数 FFT

    给一个数列,若有一个数对(i,j)满足sum[i]-sum[j-1]==S,则得到i-(j-1)的收益,求S取0到[数列总和]的每一个值时,各自的全部收益。

    神一样的构造解……

    看到数据范围这么大,又是求所有方案的累计贡献,普通的方法显然难以奏效。这时候就要考虑生成函数了。

    如果把这看成一个多项式问题,两元相乘时次数相加,系数相乘,那么让题目中的"定值"在指数上体现出来。

      ↑ ΣS <=50000,那么让x^i这一位存储S=i时的收益,那么应该计算出所有的 [i-(j-1)]*x^s ,即为路程为s时的收益

    那么就要构造能得到  [i-(j-1)]*x^s 形式的项的多项式。

    根据sum[i]-sum[j-1]==S可以有:

     Σ([ai]*x^sum[i])*Σ(x^-(sum[j-1])   -  Σ(x^sum[i])*Σ([a(j-1)]x^-(sum[j-1]) 

    这样算卷积,指数部分得到sum[i]-sum[j-1],系数部分得到所有的(i-(j-1)),岂不美哉。

    S取0的情况可以特判O(n)处理

    传说FFT会爆精度,用了Long double以后成功AC

    然后试了试NTT取超大模数强行算,对拍过了一些小数据,然而交上去TLE了

    ↑看到别人的NTT是可以过的,那就是我写的有问题,然而懒得改了先放着

    FFT:

      1 /*by SilverN*/
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #define LL long long
      8 using namespace std;
      9 const long double pi=acos(-1.0);
     10 const int mxn=350021;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 struct com{
     18     long double x,y;
     19     com operator + (const com b){return (com){x+b.x,y+b.y};}
     20     com operator - (const com b){return (com){x-b.x,y-b.y};}
     21     com operator * (const com b){return (com){x*b.x-y*b.y,x*b.y+y*b.x};}
     22 }a[mxn],b[mxn],c[mxn];
     23 int N,l,rev[mxn];
     24 void FFT(com *a,int flag){
     25     int i,j,k;
     26     for(i=0;i<N;i++)if(rev[i]>i)swap(a[rev[i]],a[i]);
     27     for(i=1;i<N;i<<=1){
     28         com wn=(com){cos(pi/i),flag*sin(pi/i)};
     29         for(j=0;j<N;j+=(i<<1)){
     30             com w=(com){1,0};
     31             for(k=0;k<i;k++,w=w*wn){
     32                 com x=a[j+k],y=w*a[j+k+i];
     33                 a[j+k]=x+y;
     34                 a[i+j+k]=x-y;
     35             }
     36         }
     37     }
     38     if(flag==-1)for(i=0;i<N;i++)a[i].x/=N;
     39     return;
     40 }
     41 int n,w[mxn];
     42 LL ans[mxn];
     43 int smm[mxn];
     44 void init(){
     45     n=read();
     46     LL cnt=0;
     47     ans[0]=0;
     48     for(int i=1;i<=n;i++){
     49         w[i]=read();
     50         smm[i]=smm[i-1]+w[i];
     51         if(!w[i]){//0
     52             cnt++;
     53             ans[0]+=cnt*(cnt+1)/2;
     54         }
     55         else cnt=0;
     56     }
     57     return;
     58 }
     59 int main(){
     60     int i,j;
     61     int T=read();
     62     
     63     while(T--){
     64         init();
     65 //        for(i=1;i<=n;i++)printf("%d ",smm[i]);
     66 //        printf("
    ");
     67         memset(a,0,sizeof a);
     68         memset(b,0,sizeof b);
     69         memset(c,0,sizeof c);
     70         int ed=smm[n];
     71         int m=ed<<1;
     72         for(N=1,l=0;N<=m;N<<=1)l++;
     73         for(i=0;i<N;i++){
     74             rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
     75         }
     76         //
     77         for(i=1;i<=n;i++){
     78             a[smm[i]].x+=i;
     79             b[ed-smm[i-1]].x+=1;
     80         }
     81         /*
     82         for(i=0;i<=ed;i++)printf("%.2Lf ",a[i].x);
     83         printf("
    ");
     84         for(i=0;i<=ed;i++)printf("%.2Lf ",b[i].x);
     85         printf("
    ");
     86         */
     87         FFT(a,1);FFT(b,1);
     88         for(i=0;i<=N;i++)
     89             c[i]=a[i]*b[i];
     90         FFT(c,-1);
     91         memset(a,0,sizeof a);
     92         memset(b,0,sizeof b);
     93         for(i=1;i<=n;i++){
     94             a[smm[i]].x+=1;
     95             b[ed-smm[i-1]].x+=i-1;
     96         }
     97         FFT(a,1);FFT(b,1);
     98         for(i=0;i<=N;i++){
     99             a[i]=a[i]*b[i];
    100         }
    101         FFT(a,-1);
    102         for(i=0;i<=N;i++)c[i]=c[i]-a[i];
    103         printf("%lld
    ",ans[0]);
    104         for(i=1;i<=ed;i++){
    105             printf("%lld
    ",(LL)(c[i+ed].x+0.5));
    106         }
    107     }
    108     return 0;
    109 }

    TLE的NTT

      1 /*by SilverN*/
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #define LL long long
      8 using namespace std;
      9 //const LL P=(1LL<<47)*7*4451+1;
     10 const LL P=479*(1<<21)+1;
     11 //const LL mod=479*(1<<21)+1;
     12 const int mxn=130021;
     13 int read(){
     14     int x=0,f=1;char ch=getchar();
     15     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     16     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     17     return x*f;
     18 }
     19 LL a[mxn],b[mxn],c[mxn];
     20 int N,l;
     21 LL mul(LL x,LL y) {
     22     LL res=0;
     23     while(y){
     24         if(y&1)res=(res+x)%P;
     25         x=(x<<1)%P;
     26         y>>=1;
     27     }
     28     return res;
     29 }
     30 LL ksm(LL a,LL k){
     31     LL res=1;
     32     while(k){
     33         if(k&1)res=mul(res,a);
     34         a=mul(a,a);
     35         k>>=1;
     36     }
     37     return res;
     38 }
     39 int rev[mxn];
     40 void NTT(LL *a,int flag){
     41     int i,j,k;
     42     for(i=0;i<N;i++)if(rev[i]>i)swap(a[rev[i]],a[i]);
     43     for(i=1;i<N;i<<=1){
     44         LL gn=ksm(3,(P-1)/(i<<1));
     45         int p=i<<1;
     46         for(j=0;j<N;j+=p){
     47             LL g=1;
     48             for(k=0;k<i;k++,g=mul(g,gn)){
     49                 LL x=a[j+k],y=mul(g,a[j+k+i]);
     50                 a[j+k]=(x+y)%P;
     51                 a[i+j+k]=(x-y+P)%P;
     52             }
     53         }
     54     }
     55     if(flag==-1){
     56         reverse(a+1,a+N);
     57         LL inv=ksm(N,P-2);
     58         for(i=0;i<N;i++)a[i]=mul(a[i],inv)%P;
     59     }
     60     return;
     61 }
     62 int n,w[mxn];
     63 LL ans[mxn];
     64 int smm[mxn];
     65 void init(){
     66     n=read();
     67     LL cnt=0;
     68     ans[0]=0;
     69     for(int i=1;i<=n;i++){
     70         w[i]=read();
     71         smm[i]=smm[i-1]+w[i];
     72         if(!w[i]){//0
     73             cnt++;
     74             ans[0]+=cnt*(cnt+1)/2;
     75         }
     76         else cnt=0;
     77     }
     78     return;
     79 }
     80 int main(){
     81     int i,j;
     82     int T=read();
     83     while(T--){
     84         init();
     85         memset(a,0,sizeof a);
     86         memset(b,0,sizeof b);
     87         memset(c,0,sizeof c);
     88         int ed=smm[n];
     89         int m=ed<<1;
     90         for(N=1,l=0;N<=m;N<<=1)l++;
     91         for(i=0;i<N;i++){
     92             rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
     93         }
     94         //
     95         for(i=1;i<=n;i++){
     96             a[smm[i]]+=i;
     97             b[ed-smm[i-1]]+=1;
     98         }
     99         
    100         NTT(a,1);NTT(b,1);
    101 //        for(i=0;i<=N;i++)printf("%lld ",a[i]);printf("
    ");
    102         for(i=0;i<=N;i++)
    103             c[i]=mul(a[i],b[i])%P;
    104         NTT(c,-1);
    105         memset(a,0,sizeof a);
    106         memset(b,0,sizeof b);
    107         for(i=1;i<=n;i++){
    108             a[smm[i]]+=1;
    109             b[ed-smm[i-1]]+=i-1;
    110         }
    111         NTT(a,1);NTT(b,1);
    112         for(i=0;i<=N;i++){
    113             a[i]=mul(a[i],b[i])%P;
    114         }
    115         NTT(a,-1);
    116         for(i=0;i<=N;i++)c[i]=(c[i]-a[i]+P)%P;
    117         printf("%lld
    ",ans[0]);
    118         for(i=1;i<=ed;i++){
    119             printf("%lld
    ",c[i+ed]);
    120         }
    121     }
    122     return 0;
    123 }
  • 相关阅读:
    BZOJ5104 二次剩余板子
    BZOJ5329 [Sdoi2018]战略游戏 圆方树+虚树
    BZOJ1095 动态点分治
    BZOJ3992: [SDOI2015]序列统计
    kd-tree板子
    thusc2018翻车记
    BZOJ5336 DP套DP
    BZOJ4316 仙人掌DP
    问题 F: 最小花费
    问题 C: 热浪
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6528952.html
Copyright © 2011-2022 走看看