其他分享
首页 > 其他分享> > CF1061C Multiplicity(dp)

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