CF1061C Multiplicity

好题笔记

CF1061C Multiplicity
这是一道用滚动数组来去优化时间和空间的dp题目,题面就不加以解释了,直接上正解。
对于这种取数的dp其实状态都是套路,第x个成为子集里第k个数与否,可以就dp[x][k]=dp[x-1][k-1]+1,如果不可以就dp[x][k]=dp[x-1][k-1],这个转移方程好去想出来,但是不论是二维数组的空间还是两层循环的时间都不可以,所以我们呢发现dp的状态只和上一个状态有关,所以可以用滚动数组来去优化空间,并且我可以在每一个数被枚举到的时候找出他的所有因数,因为假如dp[x][k]的k不是a[x]d的因数那么我们接下来的状态转移完全是没有必要的,于是我们这个转移方程就呼之欲出了,dp[k]=dp[k]+dp[k-1] (其中k是指x的因数)
注意这个题虽然我现在已经口头ac了,但是其实还是有好多细节 1.滚动数组一般都是从后往前枚举,是为了防止同一层的状态相互更新。2. 再加入因数,我们不要用sqrt,这个太慢了,直接用ii。 3. 找到因数,还要判断ii==x,如果是完全平方数的话就会压进去两次 4. 我们找到了factor,但是要注意factor<=x,x是我现在找了几个数是,才会被操作,要不然会数组越界re掉。
最后代码如下

#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000007
int n,a[100005];
void get_input(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]); 
	}
}
vector<int> fac;
getying(int x){
	for(int i=1;i*i<=x;i++){
		if(x%i==0){
			fac.push_back(i);
			if(i*i!=x) 
		  	  fac.push_back(x/i); 
		}
	}
	sort(fac.begin(),fac.end(),greater<int>() );
}



int dp[100005];
void getans(){
	dp[0]=1;
	for(int x=1;x<=n;x++){
		getying(a[x]);
		for(int i=0;i<fac.size();i++){
			if(fac[i]<=x)
				dp[fac[i]]=(dp[fac[i]]+dp[fac[i]-1])%MOD;
		}
		fac.clear();
	}
	int xum=0;
	for(int i=1;i<=n;i++){
		xum=(xum+dp[i])%MOD;
	}
	printf("%d",xum%MOD);
} 




int main(){
	get_input();
	getans();
	return 0;
}
上一篇:Educational Codeforces Round 111 (Rated for Div. 2) D.Excellent Arrays 对称 数形结合


下一篇:F - Make Pai(区间dp+计数)