CF1061C Multiplicity(dp)
作者:互联网
洛谷传送门
解题思路
最朴素的dp为:dp[i][j]前i个数选j个方案数。
\(O(n^2)\) 的时空复杂度很显然会炸,所以需要优化。
先考虑空间,第一维可以滚动数组滚掉,因为选的第j个数与上一个数是什么没关系。
再考虑时间上,尝试对于每个a[i],只枚举符合条件的j,即枚举其因数(根号复杂度)。
注意因数要从大到小枚举。
可以用一个栈一个队列维护。
所以最后时间复杂度就是 \(O(n\sqrt n)\)。
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
const int maxn=1e5+5;
const int mod=1e9+7;
int n,a[maxn],dp[maxn],ans;
queue<int> q;
stack<int> s;
template<class T>inline void read(T &x)
{
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
}
int main(){
ios::sync_with_stdio(false);
read(n);
for(int i=1;i<=n;i++) read(a[i]);
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j*j<=a[i];j++){
if(a[i]%j==0) s.push(j);
if(j*j!=a[i]) q.push(a[i]/j);
}
while(!q.empty()){
dp[q.front()]=(dp[q.front()]+dp[q.front()-1])%mod;
q.pop();
}
while(!s.empty()){
dp[s.top()]=(dp[s.top()]+dp[s.top()-1])%mod;
s.pop();
}
}
for(int i=1;i<=n;i++) ans=(ans+dp[i])%mod;
cout<<ans;
return 0;
}
标签:int,Multiplicity,复杂度,枚举,maxn,CF1061C,include,dp 来源: https://www.cnblogs.com/yinyuqin/p/15336333.html