codeforces1061c
Posted pandaking
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces1061c相关的知识,希望对你有一定的参考价值。
题意:给你一个序列a1,a2,a3,.....,an。如果其中取出一个子序列满足b1,b2,.....,bn.满足如下关系,如果对任意bi都满足bi%i==0.那么称这个序列为好好好序列,求这个序列中有多少个好好好序列。
(这道题我一开始是往区间dp和最长公共子序列那儿去想的,但是接下来就卡在了转移上面,然后还有就是数组开不下)
(然后接下来的话,我觉得这样不行,又把重心放到那儿以i结尾上升序列长度为j的数列上面了,这是我就比较接近正解了,然后预处理我也大概想好了,但是接下来不知道怎么把时间复杂度和空间复杂度降下来)
(然后接下来就有点自闭了,就一直卡住卡住,没有啥思路)
其实你的第一维是可以去掉的,这样可以起到降低空间复杂度的作用。然后往后面走的话,对当前这个长度j影响是(以前的长度j的值)加上(以前长度j-1的值),然后每次取以当前点结尾的值
下面是代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 using namespace std; 8 typedef long long ll; 9 const ll mod=1e9+7; 10 const int maxn=1000100; 11 int n; 12 vector<int> mt[maxn];//用vector啊。。。。。。。。。。 13 //为什么我一直想到是哈希,哈希。。。。。。。 14 ll dp[maxn]; 15 ll ans=0; 16 int main(){ 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++){ 19 int x; 20 scanf("%d",&x); 21 for(int j=1;j*j<=x;j++){ 22 if(x%j==0){ 23 mt[i].push_back(j); 24 if(j*j!=x) mt[i].push_back(x/j); 25 } 26 } 27 sort(mt[i].begin(),mt[i].end()); 28 } 29 dp[0]=1; 30 for(int i=1;i<=n;i++){//从1到n 31 for(int j=mt[i].size()-1;j>=0;j--){ //一点要从后到前,这样来判断。 32 dp[mt[i][j]]=(dp[mt[i][j]]+dp[mt[i][j]-1])%mod;//这个是分两种情况,一是已经达到了j个,就是不要当前这位,二是还没有到达j,要当前这样 33 ans=(ans+dp[mt[i][j]-1])%mod;//以当前这位截止的长度为j的。。。。这样可以减少重复 34 } 35 } 36 printf("%lld ",ans); 37 return 0; 38 }
以上是关于codeforces1061c的主要内容,如果未能解决你的问题,请参考以下文章
[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano](代码片段