t
a
g
:
tag:
tag:数组分段方案
动态规划
动态规划前缀和优化
同余
传送门:
题意 : 给定一个数组 a [ ] a[] a[],询问有多少种方式,可以将其分为任意段,使得其每段 B i B_i Bi满足 B i % i = = 0 B_i\%i==0 Bi%i==0
思路 : 首先这题想到的是 动态规划
状态表示 : d p [ i ] [ j ] dp[i][j] dp[i][j],表示前 i i i个数字,分成 j j j段的合法方案
状态转移: f [ i ] [ j ] = ∑ ( s u m i − s u m k ) % j = = 0 f [ k ] [ j − 1 ] f[i][j] =\sum\limits_{(sum_i-sum_k)\%j==0}f[k][j-1] f[i][j]=(sumi−sumk)%j==0∑f[k][j−1]
但是这种方法需要枚举 i , j , k i,j,k i,j,k时间复杂度 O n 3 O\ n^3 O n3,显然是不行的
因此我们考虑优化 ( s u m i − s u m k ) % j = = 0 s u m i % j = = s u m k % j \begin{aligned} &(sum_i-sum_k)\%j==0\\ &sum_i\%j==sum_k\%j\\ \end{aligned} (sumi−sumk)%j==0sumi%j==sumk%j
由上面的式子我们可以知道 现在我们只需要处理出满足 s u m [ i ] % j = = s u m [ k ] % j sum[i]\%j==sum[k]\%j sum[i]%j==sum[k]%j所有位置的 d p [ k ] [ j − 1 ] dp[k][j-1] dp[k][j−1]的和即可
因此我们再来一个 p r e [ j ] [ t ] pre[j][t] pre[j][t]表示 s u m [ i ] % j = = t sum[i]\%j==t sum[i]%j==t的 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j−1]的和
因为我们是先处理出来 p r e pre pre然后再来更新 k k k的因此,我们需要转换一下 i , j i,j i,j的顺序
code :
const int N = 3e3+10,mod = 1e9+7;
int n;
ll a[N],pre[N][N],dp[N][N],sum[N];
void solve(){
int n;cin>>n;
for(int i=1;i>a[i];
sum[i] = sum[i-1] + a[i];
}
pre[0][0] = 1;
for(int j=1;j
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?