模拟赛-20190228-随机数(random)

前言

一道暴力就要用积分的题
整理一下思路

题目相关

题目大意

n n n个实数 x 1 , x 2 ⋅ ⋅ ⋅ x n x_1,x_2···x_n x1,x2xn,其中 x i x_i xi [ l i , r i ] [l_i,r_i] [li,ri]中均匀随机
m a x ( ( ∑ x i ) m , 0 ) max((\sum x_i)^m,0) max((xi)m,0)的期望

数据范围

1 ≤ n ≤ 10 , 1 ≤ m ≤ 100 , − 1 0 6 ≤ l i ≤ r i ≤ 1 0 6 1\le n\le10,1\le m\le100,-10^6\le l_i\le r_i\le 10^6 1n10,1m100,106liri106

题解

暴力

有一档 n = 1 n=1 n=1的部分分
我们发现这档部分分很好拿,当答案为正的时候直接积分即可
因为
∫ x m = x m + 1 m + 1 \int x^m=\frac{x^{m+1}}{m+1} xm=m+1xm+1
那么
∫ l i r i x m = r i m + 1 − l i m + 1 m + 1 \int_{l_i}^{r_i} x^m=\frac{r_i^{m+1}-l_i^{m+1}}{m+1} lirixm=m+1rim+1lim+1

正解

我们发现 n n n变得比较大的时候,每个位置概率可能会有所不同,所以本题并不好做
其中 a , b a,b a,b均为一个多项式
我们构造一种用来存概率的函数 f ( x ) = { a ( x > R ) b ( x ≤ R ) f(x)=\begin{cases}a&(x>R)\\b&(x\le R)\end{cases} f(x)={ab(x>R)(xR)
我们发现,对于一组 [ l i , r i ] [l_i,r_i] [li,ri]的情况可以表示成两个函数相减即 { 0 ( x > r i ) 1 r i − l i ( x ≤ r i ) − { 0 ( x > l i ) 1 r i − l i ( x ≤ l i ) \begin{cases}0&(x>r_i)\\ \frac{1}{r_i-l_i}&(x\le r_i)\end{cases}-\begin{cases}0&(x>l_i)\\\frac{1}{r_i-l_i}&(x\le l_i)\end{cases} {0rili1(x>ri)(xri){0rili1(x>li)(xli)
而对于多组 [ l i , r i ] [l_i,r_i] [li,ri]并在一起的情况,我们发现 f ∗ g ( x ) f*g(x) fg(x)就是我们想要的运算
那么 ∏ i = 1 n ( { 0 ( x > r i ) 1 r i − l i ( x ≤ r i ) − { 0 ( x > l i ) 1 r i − l i ( x ≤ l i ) ) \prod_{i=1}^n\left(\begin{cases}0&(x>r_i)\\ \frac{1}{r_i-l_i}&(x\le r_i)\end{cases}-\begin{cases}0&(x>l_i)\\\frac{1}{r_i-l_i}&(x\le l_i)\end{cases}\right) i=1n({0rili1(x>ri)(xri){0rili1(x>li)(xli))
就是最终的概率分布函数了
我们来观察一下 f ∗ g ( x ) f*g(x) fg(x)这个运算
由于我们发现,每个函数的 a a a都是0,那么我们现先讨论 a = 0 a=0 a=0的情况

f ( x ) = { 0 ( x > R f ) b f ( x ≤ R f ) f(x)=\begin{cases}0&(x>R_f)\\b_f&(x\le R_f)\end{cases} f(x)={0bf(x>Rf)(xRf), g ( x ) = { 0 ( x > R g ) b g ( x ≤ R g ) g(x)=\begin{cases}0&(x>R_g)\\b_g&(x\le R_g)\end{cases} g(x)={0bg(x>Rg)(xRg)

为了方便,我们设 b f b_f bf b g b_g bg都是常值且值分别为 B f B_f Bf B g B_g Bg
讨论 f ∗ g ( x ) f*g(x) fg(x)的值
对于 x = x f + x g > R f + R g x=x_f+x_g>R_f+R_g x=xf+xg>Rf+Rg的情况, f ∗ g ( x ) = 0 f*g(x)=0 fg(x)=0
对于 x = x f + x g ≤ R f + R g x=x_f+x_g\le R_f+R_g x=xf+xgRf+Rg的情况, f ∗ g ( x ) = ( R f + R g − x ) B f ∗ B g f*g(x)=(R_f+R_g-x)B_f*B_g fg(x)=(Rf+Rgx)BfBg
这样的话卷积仍然是原来形式的函数,并且 a = 0 a=0 a=0,但结果的 b b b变成了一个多项式

我们进行推广,我们设 b f b_f bf是常值 B f B_f Bf b g b_g bg是一个多项式
讨论 f ∗ g ( x ) f*g(x) fg(x)的值
对于 x = x f + x g > R f + R g x=x_f+x_g>R_f+R_g x=xf+xg>Rf+Rg的情况, f ∗ g ( x ) = 0 f*g(x)=0 fg(x)=0
对于 x = x f + x g ≤ R f + R g x=x_f+x_g\le R_f+R_g x=xf+xgRf+Rg的情况, f ∗ g ( x ) = ∫ x − R f R g b f ( x + x − y ) b g ( y ) d y = ∫ x − R f R g B f ∗ b g ( y ) d y = B f ∫ x − R f R g b g ( y ) d y f*g(x)=\int_{x-R_f}^{R_g}b_f(x+x-y)b_g(y) dy=\int_{x-R_f}^{R_g}B_f*b_g(y) dy=B_f\int_{x-R_f}^{R_g}b_g(y) dy fg(x)=xRfRgbf(x+xy)bg(y)dy=xRfRgBfbg(y)dy=BfxRfRgbg(y)dy
这样的话卷积仍然是原来形式的函数,并且 a = 0 a=0 a=0,但结果 b b b的多项式次数变高 1 1 1

定义完了卷积,我们发现我们无法定义减法,因为减法的结果将不能方便的用原来函数的形式表示出来
所以我们暴力把最终的概率分布函数的值暴力展开,展开成 O ( 2 n ) \mathcal O(2^n) O(2n)
我们发现,把这 O ( 2 n ) \mathcal O(2^n) O(2n)项的值都算出来的复杂度是 O ( 2 n ∗ n 2 ) \mathcal O(2^n*n^2) O(2nn2)

得到了值分布的多项式后,我们可以将所有多项式按 R R R进行排序,然后根据区间进行积分即可

代码
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<algorithm>
namespace fast_IO
{
    const int IN_LEN=10000000,OUT_LEN=10000000;
    char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;
    inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}
    inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}
    inline void flush(){fwrite(obuf,1,oh-obuf,stdout);}
}
using namespace fast_IO;
#define getchar() getchar_()
#define putchar(x) putchar_((x))
typedef long long ll;
#define rg register
template <typename T> inline T max(const T a,const T b){return a>b?a:b;}
template <typename T> inline T min(const T a,const T b){return a<b?a:b;}
template <typename T> inline T mind(T&a,const T b){a=a<b?a:b;}
template <typename T> inline T maxd(T&a,const T b){a=a>b?a:b;}
template <typename T> inline T abs(const T a){return a>0?a:-a;}
template <typename T> inline void Swap(T&a,T&b){T c=a;a=b;b=c;}
template <typename T> inline void swap(T*a,T*b){T c=a;a=b;b=c;}
template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template <typename T> inline T square(const T x){return x*x;};
template <typename T> inline void read(T&x)
{
    char cu=getchar();x=0;bool fla=0;
    while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}
    while(isdigit(cu))x=x*10+cu-'0',cu=getchar();
    if(fla)x=-x;  
}
template <typename T> void printe(const T x)
{
    if(x>=10)printe(x/10);
    putchar(x%10+'0');
}
template <typename T> inline void print(const T x)
{
    if(x<0)putchar('-'),printe(-x);
    else printe(x);
}
const int maxn=2097152,mod=998244353;
inline int Md(const int x){return x>=mod?x-mod:x;}
template<typename T>
inline int pow(int x,T y)
{
    rg int res=1;x%=mod;
    for(;y;y>>=1,x=(ll)x*x%mod)if(y&1)res=(ll)res*x%mod;
    return res;
}
namespace Poly///namespace of Poly
{
int W_[maxn],ha[maxn],hb[maxn],Inv[maxn];
inline void init(const int x)
{
    rg int tim=0,lenth=1;
    while(lenth<x)lenth<<=1,tim++;
    for(rg int i=1;i<lenth;i<<=1)
    {
    	const int WW=pow(3,(mod-1)/(i*2));
    	W_[i]=1;
    	for(rg int j=i+1,k=i<<1;j<k;j++)W_[j]=(ll)W_[j-1]*WW%mod;
    }
    Inv[0]=Inv[1]=1;
    for(rg int i=2;i<x;i++)Inv[i]=(ll)(mod-mod/i)*Inv[mod%i]%mod;
}
int L;
inline void DFT(int*A)//prepare:init L 
{
    for(rg int i=0,j=0;i<L;i++)
    {
        if(i>j)Swap(A[i],A[j]);
        for(rg int k=L>>1;(j^=k)<k;k>>=1);
    }
    for(rg int i=1;i<L;i<<=1)
        for(rg int j=0,J=i<<1;j<L;j+=J)
            for(rg int k=0;k<i;k++)
            {
                const int x=A[j+k],y=(ll)A[j+k+i]*W_[i+k]%mod;
                A[j+k]=Md(x+y),A[j+k+i]=Md(mod+x-y);
            }
}
void IDFT(int*A)
{
    for(rg int i=1;i<L-i;i++)Swap(A[i],A[L-i]);
    DFT(A);
}
inline int Quadratic_residue(const int a)
{
    if(a==0)return 0;
    int b=(rand()<<14^rand())%mod;
    while(pow(b,(mod-1)>>1)!=mod-1)b=(rand()<<14^rand())%mod;
    int s=mod-1,t=0,x,inv=pow(a,mod-2),f=1;
    while(!(s&1))s>>=1,t++,f<<=1;
    t--,x=pow(a,(s+1)>>1),f>>=1;
    while(t)
    {
        f>>=1;
        if(pow((int)((ll)inv*x%mod*x%mod),f)!=1)x=(ll)x*pow(b,s)%mod;
        t--,s<<=1;
    }
    return min(x,mod-x);
}
struct poly
{
    std::vector<int>A;
    poly(){A.resize(0);}
    poly(const int x){A.resize(1),A[0]=x;}
    inline int&operator[](const int x){return A[x];}
    inline int operator[](const int x)const{return A[x];}
    inline void clear(){A.clear();}
    inline unsigned int size()const{return A.size();}
    inline void resize(const unsigned int x){A.resize(x);}
    void RE(const int x)
    {
        A.resize(x);
        for(rg int i=0;i<x;i++)A[i]=0; 
    }
    void readin(const int MAX)
    {
        A.resize(MAX);
        for(rg int i=0;i<MAX;i++)read(A[i]);
    }
    void putout()const
    {
        for(rg unsigned int i=0;i<A.size();i++)print(A[i]),putchar(' ');
    }
    inline poly operator +(const poly b)const
    {
        poly RES;
        RES.resize(max(size(),b.size()));
        for(rg unsigned int i=0;i<RES.size();i++)RES[i]=Md((i<size()?A[i]:0)+(i<b.size()?b[i]:0));
        return RES;
    }
    inline poly operator -(const poly b)const
    {
        poly RES;
        RES.resize(max(size(),b.size()));
        for(rg unsigned int i=0;i<RES.size();i++)RES[i]=Md((i<size()?A[i]:0)+mod-(i<b.size()?b[i]:0));
        return RES;
    }
    inline poly operator *(const int b)const
    {
        poly RES=*this;
        for(rg unsigned int i=0;i<RES.size();i++)RES[i]=(ll)RES[i]*b%mod;
        return RES;
    }
    inline poly operator /(const int b)const
    {
        poly RES=(*this)*pow(b,mod-2);
    	return RES;
    }
    inline poly operator *(const poly b)const
    {
        const int RES=A.size()+b.size()-1;
        if(A.size()<=20||b.size()<=20)
    	{
    		poly c;c.RE(RES);
    		for(rg unsigned int i=0;i<size();i++)
    			for(rg unsigned int j=0;j<b.size();j++)
    				c[i+j]=((ll)A[i]*b[j]+c[i+j])%mod;
    		return c;
    	}
        L=1;while(L<RES)L<<=1;
        poly c;c.A.resize(RES);
        memset(ha,0,L<<2);
        memset(hb,0,L<<2);
        for(rg unsigned int i=0;i<A.size();i++)ha[i]=A[i];
        for(rg unsigned int i=0;i<b.A.size();i++)hb[i]=b.A[i];
        DFT(ha),DFT(hb);
        for(rg int i=0;i<L;i++)ha[i]=(ll)ha[i]*hb[i]%mod;
        IDFT(ha);
        const int inv=pow(L,mod-2);
        for(rg int i=0;i<RES;i++)c.A[i]=(ll)ha[i]*inv%mod;
        return c;
    }
    inline poly inv()const
    {
        poly C;
        if(A.size()==1){C=*this;C[0]=pow(C[0],mod-2);return C;}
        C.resize((A.size()+1)>>1);
        for(rg unsigned int i=0;i<C.size();i++)C[i]=A[i];
        C=C.inv();
        L=1;while(L<(int)size()*2-1)L<<=1;
        for(rg unsigned int i=0;i<A.size();i++)ha[i]=A[i];
        for(rg unsigned int i=0;i<C.size();i++)hb[i]=C[i];
        memset(ha+A.size(),0,(L-A.size())<<2);
        memset(hb+C.size(),0,(L-C.size())<<2);
        DFT(ha),DFT(hb);
        for(rg int i=0;i<L;i++)ha[i]=(ll)(2-(ll)hb[i]*ha[i]%mod+mod)*hb[i]%mod;
        IDFT(ha);
        const int inv=pow(L,mod-2);
        C.resize(size());
        for(rg unsigned int i=0;i<size();i++)C[i]=(ll)ha[i]*inv%mod;
        return C;
    }
/*    inline poly inv()const
    {
        poly C;
        if(A.size()==1){C=*this;C[0]=pow(C[0],mod-2);return C;}
        C.resize((A.size()+1)>>1);
        for(rg unsigned int i=0;i<C.size();i++)C[i]=A[i];
        C=C.inv();
        poly D=(poly)2-*this*C;
        D.resize(size());
        D=D*C;
        D.resize(size());
        return D;
    }*///大常数版本 
    inline void Reverse(const int n)
    {
    	A.resize(n);
    	for(rg int i=0,j=n-1;i<j;i++,j--)Swap(A[i],A[j]);
    }
    inline poly operator /(const poly B)const
    {
    	if(size()<B.size())return 0;
        poly a=*this,b=B;a.Reverse(size()),b.Reverse(B.size());
        b.resize(size()-B.size()+1);
        b=b.inv();
        b=b*a;
        b.Reverse(size()-B.size()+1);
        return b;
    }
    inline poly operator %(const poly B)const
    {
        poly C=(*this)-(*this)/B*B;C.resize(B.size()-1);
        return C;
    }
    inline poly diff()const
    {
        poly C;C.resize(size()-1);
        for(rg unsigned int i=1;i<size();i++)C[i-1]=(ll)A[i]*i%mod;
        return C;
    }
    inline poly inte()const
    {
        poly C;C.resize(size()+1);
        for(rg unsigned int i=0;i<size();i++)C[i+1]=(ll)A[i]*Inv[i+1]%mod;
        C[0]=0;
        return C;
    }
    inline poly ln()const
    {
        poly C=(diff()*inv()).inte();C.resize(size());
        return C;
    }
    inline poly exp()const
    {
        poly C;
        if(size()==1){C=*this;C[0]=1;return C;}
        C.resize((size()+1)>>1);
        for(rg unsigned int i=0;i<C.size();i++)C[i]=A[i];
        C=C.exp();C.resize(size());
        poly D=(poly)1-C.ln()+*this;
        D=D*C;
        D.resize(size());
        return D;
    }
    inline poly sqrt()const
    {
        poly C;
        if(size()==1)
        {
            C=*this;C[0]=Quadratic_residue(C[0]);
            return C;
        }
        C.resize((size()+1)>>1);
        for(rg unsigned int i=0;i<C.size();i++)C[i]=A[i];
        C=C.sqrt();C.resize(size());
        C=(C+*this*C.inv())*(int)499122177;
        C.resize(size());
        return C;
    }
    inline poly operator >>(const unsigned int x)const
    {
    	poly C;if(size()<x){C.resize(0);return C;}
        C.resize(size()-x);
    	for(rg unsigned int i=0;i<C.size();i++)C[i]=A[i+x];
    	return C;
    }
    inline poly operator <<(const unsigned int x)const
    {
    	poly C;C.RE(size()+x);
    	for(rg unsigned int i=0;i<size();i++)C[i+x]=A[i];
    	return C;
    }
    inline poly Pow(const unsigned int x)const
    {
    	for(rg unsigned int i=0;i<size();i++)
            if(A[i])
            {
                poly C=((((*this/A[i])>>i).ln()*x).exp()*pow(A[i],x))<<(min(i*x,size()));
                C.resize(size());
                return C;
            }
    	return *this;
    }
    inline void cheng(const poly&B)
    {
        for(rg unsigned int i=0;i<size();i++)A[i]=(ll)A[i]*B[i]%mod; 
    }
    inline void jia(const poly&B)
    {
        for(rg unsigned int i=0;i<size();i++)A[i]=Md(A[i]+B[i]); 
    }
    inline void dft()
    {
        memset(ha,0,L<<2);
        for(rg unsigned int i=0;i<A.size();i++)ha[i]=A[i];
        DFT(ha);
        resize(L);
        for(rg int i=0;i<L;i++)A[i]=ha[i];
    }
    inline void idft()
    {
        memset(ha,0,L<<2);
        for(rg unsigned int i=0;i<A.size();i++)ha[i]=A[i];
        IDFT(ha);
        const int inv=pow(L,mod-2);
        for(rg int i=0;i<L;i++)A[i]=(ll)ha[i]*inv%mod;
        while(size()&&!A[size()-1])A.pop_back();
    }
    ll dai(int x)const
    {
    	x=Md(x%mod+mod);
    	ll res=0;
    	for(rg unsigned int i=0,j=1;i<size();i++,j=(ll)j*x%mod)res=((ll)A[i]*j+res)%mod;
    	return res;
    }
};
void fz(const int root,const int l,const int r,std::vector<int>&v,std::vector<poly>&A)
{
    if(l==r)
    {
        A[root].resize(2);
        A[root][0]=(mod-v[l])%mod;
        A[root][1]=1;
        return;
    }
    const int mid=(l+r)>>1;
    fz(root<<1,l,mid,v,A),fz(root<<1|1,mid+1,r,v,A);
    A[root]=A[root<<1]*A[root<<1|1];
}
void calc(const int root,const int l,const int r,std::vector<int>&v,std::vector<poly>&A,std::vector<poly>&B)
{
    if(l==r)
    {
        v[l]=B[root][0];
        return;
    }
    const int mid=(l+r)>>1;
    B[root<<1]=B[root]%A[root<<1];
    B[root<<1|1]=B[root]%A[root<<1|1];
    calc(root<<1,l,mid,v,A,B),calc(root<<1|1,mid+1,r,v,A,B);
}
void multi_point_evaluation(const poly a,std::vector<int>&v)
{
    std::vector<poly>A,B;A.resize(maxn),B.resize(maxn);
    fz(1,0,v.size()-1,v,A);
    B[1]=a%A[1];
    calc(1,0,v.size()-1,v,A,B);
}
void fz2(const int root,const int l,const int r,std::vector<int>&y,std::vector<poly>&A,std::vector<poly>&B)
{
    if(l==r)
    {
        B[root].resize(1),B[root][0]=y[l];
        return;
    }
    const int mid=(l+r)>>1;
    fz2(root<<1,l,mid,y,A,B),fz2(root<<1|1,mid+1,r,y,A,B);
    B[root]=B[root<<1]*A[root<<1|1]+B[root<<1|1]*A[root<<1];
}
poly interpolation(std::vector<int>&x,std::vector<int>&y)
{
    std::vector<poly>A,B;A.resize(maxn),B.resize(maxn);
	fz(1,0,x.size()-1,x,A);
	multi_point_evaluation(A[1].diff(),x);
	for(rg unsigned int i=0;i<x.size();i++)y[i]=(ll)y[i]*pow(x[i],mod-2)%mod;
    fz2(1,0,x.size()-1,y,A,B);
    return B[1];
}
}///namespace of Poly
int n,m,l,r,CC[13][13];
struct POLY
{
	Poly::poly a;
	int limit;
	POLY(){a.clear();limit=0;}
	POLY operator *(const POLY Y)const
	{
		POLY c;
		c.limit=limit+Y.limit;
		Poly::poly zc=a.inte();
		c.a.RE(zc.size());
		for(rg unsigned int i=0;i<zc.size();i++)
			for(rg unsigned j=0;j<=i;j++)
				c.a[j]=((ll)CC[i][j]*zc[i]%mod*pow(Md(mod-Y.limit),i-j)+c.a[j])%mod;
		c.a=((Poly::poly)zc.dai(limit)-c.a)*Y.a;
		return c;
	}
	bool operator <(const POLY b)const
	{
		return  limit<b.limit;
	}
}f[11],g[11],s[1090];
Poly::poly lj,zc;
ll ans;
int main()
{
    Poly::init(maxn);///namespace of Poly
    for(rg int i=0;i<=10;i++)
    {
    	CC[i][0]=CC[i][i]=1;
    	for(rg int j=1;j<i;j++)CC[i][j]=Md(CC[i-1][j]+CC[i-1][j-1]);
    }
	read(n),read(m);
	for(rg int i=0;i<n;i++)
	{
		int l,r;read(l),read(r);
		f[i].limit=l,g[i].limit=r;
		f[i].a=Md(mod-pow(r-l,mod-2)),g[i].a=pow(r-l,mod-2);
	}
	for(rg int i=0;i<(1<<n);i++)
	{
		if(i&1)s[i]=g[0];
		else s[i]=f[0];
		for(rg int j=1;j<n;j++)
			if(i&(1<<j))s[i]=s[i]*g[j];
			else s[i]=s[i]*f[j];
	}
	std::sort(s,s+(1<<n));
	const int sx=(m&1)?0:-1000000000;int las=1000000000;
	for(rg int i=(1<<n)-1;i>=0&&s[i].limit>sx;i--)
	{
		zc=(lj<<m).inte();
		ans+=zc.dai(las)-zc.dai(s[i].limit);
		las=s[i].limit;
		lj=lj+s[i].a;
	}
	zc=(lj<<m).inte();
	ans+=zc.dai(las)-zc.dai(sx);
	ans=Md(ans%mod+mod);
	print(ans);
	return flush(),0;
}
总结

一道感觉挺裸的积分题
式子推错调了好久

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值