首页 > 其他分享 >Atcoder Regular Contest 118 F - Growth Rate

Atcoder Regular Contest 118 F - Growth Rate

时间:2023-07-14 21:22:04浏览次数:47  
标签:Atcoder sdp Contest int lim 插值 Regular MAXN dp

想到插值其实就挺套路的了吧……

设 \(dp_{i,j}\) 表示有多少种方法确定 \(a_i\sim a_n\) 使得 \(a_i=j\)。那么有 \(dp_{i,j}=\sum\limits_{k\ge ja_i}dp_{i+1,k}\)。边界条件是 \(dp_{n+1,1\sim m}=1\)。不难发现复杂度与值域有关,一眼过不去的样子。

考虑优化,记 \(lim_i\) 满足 \(lim_{n+1}=m\),\(lim_i=\lfloor\dfrac{lim_{i+1}}{a_i}\rfloor\)。那么显然 \(dp_i\) 只有前 \(lim_i\) 位是有用的,而如果我们设 \(sdp_{i,j}=\sum\limits_{k=1}^jdp_{i,k}\),那么 \(dp_{i,j}=sdp_{i+1,lim_{i+1}}-sdp_{i+1,ja_i-1}(j\le lim_i)\)。可以递归证明 \(dp_{i,j}\) 是关于 \(j\) 的 \(n-i+1\) 次多项式,\(sdp_{i,j}\) 是关于 \(j\) 的 \(n-i+2\) 次多项式,再结合 \(n\) 比较小不难想到插值。如果直接用“存系数”的方法维护一个多项式显然实现起来比较复杂,比较简单的方法是直接维护前 \(n-i+1\) 项的点值,由于插值可以线性,所以从 \(dp_{i+1}\) 推到 \(dp_i\) 只需要带入 \(n-i+1\) 个点值,这样复杂度是 \(O(n^3)\) 的。很 trivial 的优化的 \(a\) 中非一元素个数是 \(O(\log V)\) 的,因此对每个 \(a_i\ne 1\) 才需要暴力跑 \(O(n)\) 次插值,对于 \(a_i=1\) 只需求出 \(sdp_{i+1,lim_{i+1}}\),后面 \(sdp_{i+1,j-1}\) 查表即可。

时间复杂度 \(O(n^2\log V)\)。

const int MAXN=1005;
const int MOD=998244353;
int n,a[MAXN+5],fac[MAXN+5],ifac[MAXN+5];ll M,lim[MAXN+5];
void init_fac(int n){
	for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++)ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
	for(int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
}
vector<int>f[MAXN+5],sf[MAXN+5];
int calc(int p,ll v){
	v%=MOD;int c=n+2-p,res=0;if(v<=c)return sf[p][v];
	static int pre[MAXN+5],suf[MAXN+5];pre[0]=v;suf[c+1]=1;
	for(int i=1;i<=c;i++)pre[i]=1ll*pre[i-1]*(v-i+MOD)%MOD;
	for(int i=c;~i;i--)suf[i]=1ll*suf[i+1]*(v-i+MOD)%MOD;
	for(int i=0;i<=c;i++){
		int prd=1ll*ifac[i]*ifac[c-i]%MOD*sf[p][i]%MOD;
		if(i!=0)prd=1ll*prd*pre[i-1]%MOD;prd=1ll*prd*suf[i+1]%MOD;
		if((c-i)&1)prd=MOD-prd;res=(res+prd)%MOD;
	}return res;
}
int main(){
	scanf("%d%lld",&n,&M);for(int i=1;i<=n;i++)scanf("%d",&a[i]);init_fac(MAXN);
	for(int i=1;i<=n+1;i++)f[i].resize(n+3-i),sf[i].resize(n+3-i);
	lim[n+1]=M;for(int i=n;i;i--)lim[i]=lim[i+1]/a[i];
	f[n+1][1]=sf[n+1][1]=1;
	for(int i=n;i;i--){
		int mx=n+2-i,val_lim=calc(i+1,lim[i+1]);
		for(int j=1;j<=mx;j++)f[i][j]=(val_lim-calc(i+1,(1ll*j*a[i]-1+MOD)%MOD)+MOD)%MOD;
		for(int j=1;j<=mx;j++)sf[i][j]=(sf[i][j-1]+f[i][j])%MOD;
	}printf("%d\n",calc(1,lim[1]));
	return 0;
}

标签:Atcoder,sdp,Contest,int,lim,插值,Regular,MAXN,dp
From: https://www.cnblogs.com/tzcwk/p/arc118F.html

相关文章

  • Atcoder AGC062C Mex of Subset Sum
    对\(a_i\)从小到大进行排序,因为想到若\(<a_{i-1}\)的不能取到的数因为\(a_i>a_{i-1}\)肯定是能保证取不到的。对排完序的\(a_i\)做一个前缀和\(s_i=\sum\limits_{j=1}^n\),令\(A_i\)为\(a_{1\simi}\)中无法表示为子序列之和且\(<s_i\)的正整数的集合......
  • SMU Summer 2023 Contest Round 3
    SMUSummer2023ContestRound3A-CurriculumVitae思路:要求0后不能有1,当某个数都不删时,值为前面所有的0的个数加后面所有1的个数,求出最大即可#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongtypedefpair<int,int>PII;typedefpair<string,int>......
  • SMU Summer 2023 Contest Round 2
    SMUSummer2023ContestRound2A-TreasureHunt思路:判断Δx和Δy能否分别整除x和y,求出需要的步数,两者的步数须同奇或同偶#include<bits/stdc++.h>usingnamespacestd;//#defineintlonglongtypedefpair<int,int>PII;typedefpair<string,int>PSI;type......
  • SMU Summer 2023 Contest Round 1
    SMUSummer2023ContestRound1A-TheContest思路:求出最短解决问题总时间,在所有区间找出大于等于总时间的最短时刻。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongtypedefpair<int,int>PII;typedefpair<string,int>PSI;typedefpair<strin......
  • SMU Summer 2023 Contest Round 3
    A.CurriculumVitae题意:给出一串01序列,可以删除任意个元素,使得1后面没有0思路:枚举01分界点,使得统计前面0的个数和后面1的个数,取最大值。点击查看代码#include<bits/stdc++.h>usingnamespacestd;inta[110];intmain(){ios::sync_with_stdio(0),cin.tie(0),co......
  • AtCoder Beginner Contest 294
    A-Filter#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongint32_tmain(){ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);intn;cin>>n;for(intx;n;n--){cin>&......
  • AtCoder Beginner Contest 309 - D(最短路)
    目录D-AddOneEdge法一:dijkstra法二:BFS+队列题目传送门:abc309前面的简单题就不放了D-AddOneEdge题意:给你一个无向图图,分为两个连通块,一个顶点数为n1(1~n1),一个顶点数为n2(n1+1~n1+n2),图中共有m条边。如果现在在两个连通块之间连接一条边,那么顶点1与顶点n1+n2......
  • SMU Summer 2023 Contest Round 1
    A.TheContest题意:要做n道题,每道题花费时间a[i],但是只有几个时间段可以提交,问最早什么时间可以完成。思路:直接计算做完全部的题目所花费的时间,然后找到可以提交的时间段,和左端取最大值,就能得出结果。点击查看代码#include<bits/stdc++.h>usingnamespacestd;constint......
  • AtCoder Beginner Contest 162
    AtCoderBeginnerContest162ABCD全暴力E数学题看不懂,感性理解F线性dp,非常基础我不会,寄E-SumofgcdofTuples(Hard)看了题解发现好多做法都是推一堆式子,我实在看不懂(卷积莫反啥啥的呜呜呜)然后看见这个感觉比较好感性理解:(来自洛谷题解)#include<bits/stdc++.h>#def......
  • Atcoder Regular Contest 114 F - Permutation Division
    显然分成\(k\)段以后,最大化形成的排列的字典序的策略是将所有段按第一个元素的大小降序排列。由于最终排列的字典序肯定\(\ge\)原排列的字典序,因此我们考虑最大化最终排列与原排列的LCP,这部分就考虑二分答案,记\(dp_i\)表示以\(p_1\)开始\(p_i\)结尾的LDS的长度,那么......