首页 > 其他分享 >[ARC178E] Serval Survival

[ARC178E] Serval Survival

时间:2024-08-16 10:28:09浏览次数:12  
标签:Cmul int Survival Serval ARC178E mid pos binom sum

My Blogs

[ARC178E] Serval Survival

非常生气,点开一道看起来很正常的计数,推着推着就发现需要多项式/fn。

首先对于“撞上了之后调头”这种东西有经典的思想:可以看成是互相穿过并没有调头。但是因为要求第 \(i\) 只猫走过的路,所以可以看成是和撞上的猫互换身份。

手玩一下可以发现,如果第 \(i\) 只猫向左走,它会和 \(a_i\) 左边的第一只向右的猫互换身份,然后和 \(a_i\) 右边的第一只向左的猫互换身份,然后和 \(a_i\) 左边的第二只猫向右的猫互换身份\(\dots\),位置指的都是初始位置。

第 \(i\) 只猫走的路程就等于最后一只和他交换身份的猫直走能走的路程(向右为 \(L-a_i\),向左为 \(a_i\))。据此,我们可以找出第 \(i\) 只猫的策略。

设 \(a_i\) 左边向右走的猫的集合为 \(L\),\(a_i\) 右边向左走的猫的集合为 \(R\),分类讨论:

1.\(|L|>|R|\)

如果他向左走,最后和他交换身份的猫是 \(L\) 中从右向左第 \(|R|+1\) 只猫。如果他向右走则是 \(L\) 中从右向左第 \(|R|\) 只猫。因为是向右走,显然靠左边的猫一定走的更远,所以此时他一定会向左走。

2.\(|L|<|R|\)

和上文同理,一定会选择向右走。

3.\(|L|=|R|\)

此时他有两种策略:选择 \(L\) 中最靠左的 \(L-a_i\) 和 \(R\) 中最靠右的 \(a_i\),这是唯一有决策的点,需要选较大值。

考虑暴力 DP:设 \(ans_i\) 表示第 \(i\) 只猫的答案。

第一种情况 \(|L|>|R|\):

\[\begin{aligned} ans_i&=\sum_{j=1}^i(L-a_j)2^{j-1}\sum_{k=0}^{i-j-1}\binom{i-j-1}{k}\binom{n-i}{k}\\ &=\sum_{j=1}^i(L-a_j)2^{j-1}\sum_{k=0}^{i-j-1}\binom{i-j-1}{k}\binom{n-i}{n-i-k}\\ &=\sum_{j=1}^i(L-a_j)2^{j-1}\binom{n-j-1}{n-i}\end{aligned} \]

上面使用了范德蒙德卷积化简。发现组合数可以拆成 \(i,j,i-j\) 相关的式子,可以 FFT。

对于 \(|L|<|R|\) 的情况同理,可以把整个序列倒过来做一遍。

第二种情况 \(|L|=|R|\),假设最大值在右侧取到:

\[\begin{aligned} ans_i&=\sum_{j=i+1}^n a_j\sum_{k=0}^{j-i-1}\binom{j-i-1}{k}\binom{i-L_j}{k+1}\\ &=\sum_{j=i+1}^n a_j\sum_{k=0}^{j-i-1}\binom{j-i-1}{k}\binom{i-L_j}{i-L_j-k-1}\\ &=\sum_{j=i+1}^n a_j\binom{j-1-L_j}{i-1-L_j} \end{aligned} \]

\(L_i\) 表示最小的 \(j\) 满足 \(m-a_j<a_i\)。还是范德蒙德卷积,但是这个式子并不好用 FFT 处理。考虑写成生成函数形式,令 \(Ans(x)\) 表示 \(\sum_{i=0}^n ans_i x^i\),则:

\[Ans(x)=\sum_{j=2}^n a_j (1+x)^{j-1-L_j}x^{1+L_j} \]

\((1+x)^{j-1-L_j}\) 是为了构造组合数系数,\(x^{1+L_j}\) 是因为 \(j\) 对 \(i\) 贡献,\(i\) 的下指标是 \(i-L_j-1\),需要做一个整体平移。

因为 \(L\) 是单减的,\(i-1-L_i\) 是单增的,可以分治解决:设 \(A_i\) 表示 \(L_i+1\),\(B_i\) 表示 \(i-1-L_i\),\((1+x)^{B_l}x^{A_r}F_{l,r}(x)\) 表示 \(l,r\) 区间对答案的贡献。合并:

\[F_{l,r}(x)=F_{l,mid}(x)x^{A_r-A_{mid}}+F_{mid+1,r}(x)(1+x)^{B_{mid+1}-B_l} \]

合并的时候暴力 FFT 即可。这样最终答案就是 \((1+x)^{B_{pos}}x^{A_n}F_{pos,n}(x)\),\(pos\) 表示最小的 \(i\) 满足 \(i-1-L_i>0\)。因为 \(A,B\) 的值域都是 \(n\) 的,一个点最多被 \(\log n\) 次 FFT 包含,可以分析出复杂度是 \(\mathcal O(n\log^2 n)\)。代码写得很烂。

namespace Poly
{
    const int MAXN=400000;
    int Shape,Invn[MAXN+10],R[MAXN*4+10],Prt[MAXN*4];
    inline void init()
    {
        Invn[0]=1;
        for(int i=1;i<=MAXN;++i)Invn[i]=Cmul(Invn[i-1],i);
        int tmp=power(Invn[MAXN],MOD-2);
        for(int i=MAXN;i>=1;--i)Invn[i]=Cmul(tmp,Invn[i-1]),Mmul(tmp,i);
    }
    inline int inv(int x){return x<=MAXN?Invn[x]:power(x,MOD-2);}
    inline void NTT(vi&A,int n,int opt)
    {
        static ull B[MAXN*4+10];ull iv=power(n,MOD-2);A.resize(n);
        for(int i=0;i<n;++i)B[i]=A[R[i]];
        for(int mid=1;mid<n;mid<<=1)
        {
            for(int j=0;j<n;j+=mid<<1)
            {
                for(int k=j;k<j+mid;++k)
                {
                    ull x=B[k],y=Prt[mid+k-j]*B[k+mid]%MOD;
                    B[k]=x+y,B[k+mid]=x+MOD-y;
                }
            }
        }
        if(opt)for(int i=0;i<n;++i)A[i]=B[i]%MOD;
        else{reverse(B+1,B+n);for(int i=0;i<n;++i)A[i]=Cmul(B[i]%MOD,iv);}
    }
    inline void init(int lim)
    {
        if(lim==Shape)return;
        int n=lim/2;Shape=lim;
        for(int i=0;i<lim;++i)R[i]=(R[i>>1]>>1)|((i&1)?n:0);
        for(int i=1;i<lim;i<<=1)
        {
            int wm=power(Root,(MOD-1)/(i<<1));Prt[i]=1;
            for(int j=1;j<i;++j)Prt[i+j]=Cmul(Prt[i+j-1],wm);
        }
    }
    inline vi FFT(vi A,vi B,int N1=-1,int N2=-1)
    {
        if(N1!=-1)A.resize(N1+1);if(N2!=-1)B.resize(N2+1);
        int n=A.size()-1,m=B.size()-1,N=1,len=0;
        while(N<=n+m)N<<=1,++len;
        init(N),NTT(A,N,1),NTT(B,N,1);
        for(int i=0;i<N;++i)A[i]=Cmul(A[i],B[i]);
        return NTT(A,N,0),A.resize(n+m+1),A;
    }
}
int n,m,dl,fr[100010],inv[100010],pre[100010],suf[100010],ans[100010];
int a[100010],L[100010],R[100010],pw[100010],b[100010],res[100010];
inline int C(int n,int m){return m<0||m>n?0:Cmul(fr[n],inv[m],inv[n-m]);}
vi add(vi L,vi R)
{
	int N=max(L.size(),R.size());L.resize(N),R.resize(N);
	for(int i=0;i<N;++i)Madd(L[i],R[i]);
	return L;
}
vi move(vi A,int x)
{
	A.resize(A.size()+x);
	for(int i=A.size()-1;i>=x;--i)A[i]=A[i-x];
	for(int i=0;i<x;++i)A[i]=0;
	return A;
}
vi Binom(vi A,int x)
{
	vi B(x+1);
	for(int i=0;i<=x;++i)B[i]=C(x,i);
	A=Poly::FFT(A,B);
	return A;
}
vi A,B;
vi solve(int l,int r)
{
	if(l==r)return {a[l]};
	int mid=l+((r-l)>>1);
	return add(move(solve(l,mid),B[mid]-B[r]),
	Binom(solve(mid+1,r),A[mid+1]-A[l]));
}
void solve()
{
	A.resize(n+1),B.resize(n+1);
	int pos=0;
	for(int i=1;i<=n;++i)
	{
		if(i-1-L[i]>=0)A[i]=i-1-L[i],B[i]=L[i]+1;
		else A[i]=B[i]=0,pos=i;
	}
	for(int i=pos+1;i<=n;++i)Mdel(res[i],a[i]);
	vi D;
	if(pos<n)D=move(Binom(solve(pos+1,n),A[pos+1]),B[n]);
	for(int i=1;i<(int)D.size();++i)Madd(res[i],D[i]);
}
inline void mian()
{
	Poly::init(),read(n,m),fr[0]=inv[0]=pw[0]=1;
	for(int i=1;i<=n;++i)fr[i]=Cmul(fr[i-1],i),pw[i]=Cmul(pw[i-1],2);
	inv[n]=power(fr[n],MOD-2);
	for(int i=n-1;i>0;--i)inv[i]=Cmul(inv[i+1],i+1);
	for(int i=1;i<=n;++i)read(a[i]),b[i]=m-a[i];
	a[0]=-inf,a[n+1]=inf,b[0]=inf,b[n+1]=-inf;
	for(int i=n,r=0;i>=1;R[i--]=r)
	{
		suf[i]=Cadd(suf[i+1],Cmul(power(2,n-i),a[i]));
		while(a[r+1]<b[i])++r;
	}
	for(int i=1,l=n+1;i<=n;L[i++]=l)
	{
		pre[i]=Cadd(pre[i-1],Cmul(power(2,i-1),b[i]));
		while(b[l-1]<=a[i])--l;
	}
	write(Cadd(max(a[1],b[1])%MOD,suf[2]),'\n');
	if(n==1)return;
	if(n==2)return write(Cadd(max(a[n],b[n])%MOD,pre[n-1]));
	for(int i=n;i>1;--i)Madd(dl,Cmul(a[i],pw[n-i]));
	vi X={0},Y={0},Z={0};Z.resize(n+1);
	for(int i=1;i<=n;++i)X.eb(Cmul(b[i],pw[i-1],fr[n-i-1]));
	for(int i=1;i<=n;++i)Y.eb(inv[i-1]);
	for(int i=1;i<n;++i)Z[i]=Cmul(a[n-i+1],pw[i-1],fr[n-i-1]);
	X=Poly::FFT(X,Y),Z=Poly::FFT(Z,Y);
	for(int i=2;i<n;++i)
	{
		ans[i]=Cadd(Cmul(X[i],inv[n-i]),max(a[i],b[i])%MOD,suf[i+1],pre[i-1],Cmul(inv[i-1],Z[n-i+1]));
		Madd(dl,Cmul(b[i-1],pw[i-2]));
		Mdel(dl,Cmul(a[i],pw[n-i]));
		Mdel(ans[i],dl);
	}
	solve();
	for(int i=1;i<=n;++i)Madd(ans[i],res[i]);
	memset(res,0,sizeof(res));int v=a[n];
	for(int i=1;i<=n;++i)a[i]=b[n-i+1],L[i]=n-R[n-i+1]+1;
	solve();
	for(int i=1;i<=n;++i)Madd(ans[i],res[n-i+1]);
	for(int i=2;i<n;++i)write(ans[i],'\n');
	if(n>1)write(Cadd(max(v,b[n])%MOD,pre[n-1]));
}

标签:Cmul,int,Survival,Serval,ARC178E,mid,pos,binom,sum
From: https://www.cnblogs.com/WrongAnswer90/p/18362386

相关文章

  • R语言生存分析:生存分析(survival analysis)与生存资料有关的概念详解
     R语言生存分析:生存分析(survivalanalysis)与生存资料有关的概念详解目录R语言生存分析(survivalanalysis)与生存资料有关的概念详解#生存分析#生存资料特点#终点事件#生存时间#截尾的主要原因#生存分析研究的内容#生存分析概念大全 #生存分析对一个或多个非负......
  • 【ARK Survival Evolved】方舟:生存进化一键使用服务器开服联机教程
    1、进入控制面板2、第一次购买服务器会安装游戏端,大约5分钟左右,如果长时间处于安装状态请联系客服3、设置游戏端口方舟生存进化的设置需要三个端口,它们用于游戏端口(必须为首选端口),查询端口,RCON端口服务器创建时默认会有一个首选端口,既为我们的游戏端口(游戏端口必须为首......
  • CF1789F Serval and Brain Power 题解
    题目链接点击打开链接题目解法好有技巧性的题(感觉\(n\le80\)这个数据范围就很奇怪啊)首先可以发现\(k\le3\)是好做的,只要枚举断点,然后\(dp\)做一遍\(lcs\)即可,时间复杂度为\(O(n^{2k+1})\),不过严重跑不满,所以可以跑\(k=4\)的情况和\(k=2\)的情况是相同的,所以不......
  • R语言中的生存分析Survival analysis晚期肺癌患者4例
    原文链接:http://tecdat.cn/?p=10278原文出处:拓端数据部落公众号 第1部分:生存分析简介 本演示文稿将介绍生存分析,参考: Clark,T.,Bradburn,M.,Love,S.,&Altman,D.(2003).SurvivalanalysispartI:Basicconceptsandfirstanalyses.232-238.ISSN0007-09......
  • C. Serval and Toxel's Arrays 组合数学
    题目链接......
  • 带你读论文丨S&P21 Survivalism: Living-Off-The-Land 经典离地攻击
    本文分享自华为云社区《[论文阅读](21)S&P21Survivalism:Living-Off-The-Land 经典离地攻击》,作者:eastmount。摘要随着恶意软件检测算法和方法变得越来越复杂(sophisticated),恶意软件作者也采用(adopt)同样复杂的逃避机制(evasionmechansims)来对抗(defeat)它们。民间证据表明离......
  • Survival analysis
    准备工作#安装R包#install.packages(c("survival","survminer"))#加载R包library(survival)library(survminer)#survival包里包含的数据集data(package="survival")#以肺癌数据为例,显示数据前六行head(lung)##insttimestatusagesexph.ecogph.karnopat.kar......
  • CodeForces 1789F Serval and Brain Power
    洛谷传送门CF传送门很牛逼的题啊!感觉套路很实用,感谢ntf。考虑\(totlen=cnt\timeslen\le80\)。若\(cnt\le3\),可以\(O(|S|^{2cnt-1})\)暴力枚分割点。\(c......
  • CF1789 Codeforces Round 853 (Div. 2) D. Serval and Shift-Shift-Shift
    https://codeforces.com/contest/1789/problem/D给定两个n位二进制数a,b,你可以每次使\(a=a\oplusa>>k\)或\(a=a\oplusa<<k\),你需要用不超过n次操作......
  • CF1789D Serval and Shift-Shift-Shift 题解
    题目链接题目分析首先,看到题目中的左移右移之后再异或,我们自然可以想到在移动的过程中字符串的一段前缀和后缀不会改变,考虑通过这个性质逐位还原。因为异或0不会改变......