题面

传送门

分析

考虑DP

设\(dp[i][j]\)表示前i个数选出的序列长度为j的方案数

状态转移方程为:

\[dp[i][j]= \begin{cases}dp\left[ i-1\right] \left[ j-1\right] +dp\left[ i-1\right] \left[ j-1\right] ,j \equiv 0 (\mod i) \\ dp\left[ i-1\right] \left[ j-1\right],otherwise \end{cases}
\]

如果二维DP,直接从1~n枚举i,j,显然会MLE

发现第一维状态i只和i-1有关,考虑用类似01背包的方法去掉一维

设dp[j]表示长度为j时的状态

第i-1次循环结束后,\(dp[j]\)存储的是原来\(dp[i-1][j]\)的值

然后我们类似01背包,倒序循环j (j为i的因数,若j不是i的因数,dp值不变,不必循环) dp[j]+=dp[j-1]

我们更新dp[j]时,dp[j-1]存的还是原来\(dp[i-1][j-1]\)的值,这样便不会重复更新

另外,因数个数怎么解决呢

我们用这样的筛法,可以在\(O(n\log n)\)的时间内筛出1~n的因数

vector<int>d[maxA];
void sieve(int x){
for(int i=1;i<=x;i++){
for(int j=1;j<=x/i;j++){
d[i*j].push_back(i);
}
}
}

所以总的时间复杂度为\(O(n\log \max(a_i))\)

代码

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#define maxn 100005
#define maxA 1000005
#define mod 1000000007
using namespace std;
int n;
int maxa;
int a[maxn];
int dp[maxA];
vector<int>d[maxA];
void sieve(int x){
for(int i=1;i<=x;i++){
for(int j=1;j<=x/i;j++){
d[i*j].push_back(i);
}
}
}
int cmp(int x,int y){
return x>y;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
maxa=max(maxa,a[i]);
}
dp[0]=1;
sieve(maxa);
for(int i=1;i<=n;i++){
for(int j=d[a[i]].size()-1;j>=0;j--){
int x=d[a[i]][j];
dp[x]+=dp[x-1];
dp[x]%=mod;
}
}
long long ans=0;
for(int i=1;i<=n;i++){
ans+=dp[i];
}
ans%=mod;
cout<<ans;
}

Codeforces 1061C (DP+滚动数组)的更多相关文章

  1. HDU 1024 Max Sum Plus Plus --- dp+滚动数组

    HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值, ...

  2. POJ 3666 Making the Grade (DP滚动数组)

    题意:农夫约翰想修一条尽量平缓的路,路的每一段海拔是A[i],修理后是B[i],花费|A[i] – B[i]|,求最小花费.(数据有问题,代码只是单调递增的情况) #include <stdio ...

  3. HDU 5119 Happy Matt Friends (背包DP + 滚动数组)

    题目链接:HDU 5119 Problem Description Matt has N friends. They are playing a game together. Each of Matt ...

  4. USACO 2009 Open Grazing2 /// DP+滚动数组oj26223

    题目大意: 输入n,s:n头牛 s个栅栏 输入n头牛的初始位置 改变他们的位置,满足 1.第一头与最后一头的距离尽量大 2.相邻两头牛之间的距离尽量满足 d=(s-1)/(n-1),偏差不超过1 3. ...

  5. Codeforces 712 D. Memory and Scores (DP+滚动数组+前缀和优化)

    题目链接:http://codeforces.com/contest/712/problem/D A初始有一个分数a,B初始有一个分数b,有t轮比赛,每次比赛都可以取[-k, k]之间的数,问你最后A ...

  6. Hello 2019 D 素因子贡献法计算期望 + 概率dp + 滚动数组

    https://codeforces.com/contest/1097/problem/D 题意 给你一个n和k,问n经过k次操作之后留下的n的期望,每次操作n随机变成一个n的因数 题解 概率dp计算 ...

  7. BZOJ-1925 地精部落 烧脑DP+滚动数组

    1925: [Sdoi2010]地精部落 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1053 Solved: 633 [Submit][Status ...

  8. hdu 1513 && 1159 poj Palindrome (dp, 滚动数组, LCS)

    题目 以前做过的一道题, 今天又加了一种方法 整理了一下..... 题意:给出一个字符串,问要将这个字符串变成回文串要添加最少几个字符. 方法一: 将该字符串与其反转求一次LCS,然后所求就是n减去 ...

  9. 【BZOJ】1925: [Sdoi2010]地精部落 DP+滚动数组

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1925 题意:输入一个数N(1 <= N <= 4200),问将这些数排列成折线 ...

随机推荐

  1. 初学Java 数组统计字母

    public class CountLetterInArray { public static void main(String[] args) { char[] chars = createArra ...

  2. ps:不规则选区

    尽管我们学会了如何添加减去或是交叉选区,但选取出来的选区还是比较规则,不是矩形就是圆形,这样的形状很难胜任在实际制作中的需要.现在我们就要学习如何建立一个任意形状的选区.建立任意选区的工具是套索工具. ...

  3. Ansible笔记(2)---常用模块之文件操作

    一.copy模块 1.1作用: copy模块是将ansible主机上的文件拷贝到远程受控主机 1.2常用参数: src参数 :用于指定需要copy的文件或目录. dest参数 :用于指定文件将被拷贝到 ...

  4. Julia 语言

    同时安装多个库 Pkg.add.(["IJulia", "Combinatorics", "Plots", "TaylorSeri ...

  5. eclipse 报错:One or more constraints have not been satisfied.

    接受 我有同样的问题.在我的maven项目中添加速度依赖关系后,我在标记选项卡中得到相同的错误.然后我注意到maven项目创建的web.xml文件具有servlet2.3模式.当我将其更改为servl ...

  6. Docker Toolbox 学习教程【转载】

    最近在研究虚拟化,容器和大数据,所以从Docker入手,下面介绍一下在Windows下怎么玩转Docker.Docker本身在Windows下有两个软件,一个就是Docker,另一个是Docker T ...

  7. Linux内核设计与实现 总结笔记(第二章)

    一.Linux内核中的一些基本概念 内核空间:内核可独立于普通应用程序,它一般处于系统态,拥有受保护的内存空间和访问硬件设备的所有权限.这种系统态和被保护起来的内存空间,称为内核空间. 进程上下文:当 ...

  8. Python_007(深浅拷贝)

    一.基础数据类型的补充 1.其他类型之间的相互转换 例如:str = int(str) str => int; int = list(int) int => list;  tuple = ...

  9. wl

    <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...

  10. C++ 拷贝构造函数与赋值函数的区别(很严谨和全面)

    这里我们用类String 来介绍这两个函数: 拷贝构造函数是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用.当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式 ...