• 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)

    具体看代码:

     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
    ",Solve());
    55 }
    View Code

      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掉了......

  • 相关阅读:
    ASP.NET 实现邮件发送和接受的功能(Sockets)
    使用Sql server进行分布式查询
    Sqlserver中的一些技巧
    使用sql server中的全文索引
    水晶报表的装载和修改文本
    创建作业的通用存储过程
    MS SQL数据库备份和恢复
    数据库运用XML操作
    安装程序自动安装数据库
    ASP.NET 实现邮件发送和接受的功能(Mail)
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10028467.html
Copyright © 2020-2023  润新知