Codeforces Round #523 (Div. 2) C Multiplicity (DP)
https://www.cnblogs.com/violet-acmer/p/10005351.html
题意:
给定一数组a[],从a[ ]中除去任意个元素得到b[ ],求能形成多少“好序列”;
好序列的定义是:对于任意的 i 有 b[i]%i == 0(1 ≤ i ≤ size_b[ ])。
题解:
相关变量解释:
1 int n; 2 int a[maxn]; 3 int dp[maxn];//dp[i] : 下标i处可以获得的最大的"好序列" 4 int factor[maxn];//factor[i] : 记录a[i]的因子
步骤:
(1):从a[1]开始遍历整个数组;
(2):来到a[i]处,将a[i]因式分解,找到其所有的因子factor,并判断其是否在[1,i ]范围内,如果在dp[factor] += dp[factor-1];(对于所有的factor)
具体看代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 const int MOD=1e9+7; 9 const int maxn=1e5+10; 10 11 int n; 12 int a[maxn]; 13 int dp[maxn];//dp[i] : 下标i处可以获得的最大的"好序列" 14 int factor[maxn];//factor[i] : 记录a[i]的因子 15 16 void updataDp(int i) 17 { 18 int index=1; 19 for(int j=1;j*j <= a[i];++j) 20 { 21 if(a[i]%j == 0)//判断j是否为a[i]的因子 22 { 23 factor[index++]=j;//记录a[i]的因子 24 if(a[i]/j != j && a[i]/j <= i)//判断其另一个因子a[i]/j是否 <= i,并判断其是否等于 j 25 factor[index++]=a[i]/j; 26 } 27 } 28 sort(factor+1,factor+index); 29 for(int j=index-1;j >= 1;--j)//从大因子到小因子,防止a[i]的小因子影响大因子 30 { 31 int x=factor[j]; 32 dp[x] += dp[x-1]; 33 dp[x] %= MOD; 34 } 35 } 36 int Solve() 37 { 38 mem(dp,0); 39 dp[0]=1; 40 for(int i=1;i <= n;++i)//遍历a[] 41 updataDp(i);//由a[i]更新dp[] 42 43 int res=0; 44 for(int i=1;i <= n;++i) 45 res=res%MOD+dp[i]; 46 47 return res%MOD; 48 } 49 int main() 50 { 51 scanf("%d",&n); 52 for(int i=1;i <= n;++i) 53 scanf("%d",a+i); 54 printf("%d\n",Solve()); 55 }
AC前的错误代码分析:
1 void updataDp(int i) 2 { 3 for(int j=1;j < i;++j) 4 if(a[i]%(j+1) == 0) 5 dp[j+1] += dp[j],dp[j+1] %= MOD; 6 dp[1]++; 7 }
①:从小因子到大因子更新dp[ ],在第五组数据就wa了
根据dp定义,dp[ i ]指的是当前元素a[i]在去点其之前的若干个元素后可以形成的“好序列”个数,终点是“其之前”,如果从小因子到大因子更新dp[ ],
dp[bigFactor] += dp[bigFactor-1];如果bigFactor-1是a[i]的因子,那么这个因子就会给dp[bigFactor]做贡献,而实际是不需要。
②:查找a[i]的因子是从1遍历到i,在第八组数据TLE
此算法的时间复杂度为O(N^2),当然会TLE了,然后,实在是没辙了,就去翻了翻大佬博客,发现这篇博客上使用vector存储的a[i]的所有因子,在
查找a[ i ]的所有因子时的时间复杂度是sqrt(n),当我看到sort排序的时候有点纳闷,加个O(nlogn)的排序难道不超时?
后来仔细想了一下,a[ i ]的所有因子很少(106才49个因子),所以用sort顶多是O(1)的时间复杂度,而整体时间复杂度为O(n√n),当然就轻轻松松的A掉了......