欢迎来爆踩我~|

AFewSuns

园龄:4年11个月粉丝:42关注:3

CF1061C Multiplicity

题目传送门

题目大意

从序列a1,a2,,an中选出非空子序列b1,b2,,bk,一个子序列合法需要满足i[1,k],i|bi。求有多少互不相等的合法子序列,答案对109+7取模。

思路

一看到题,就会想起dp,然后根据这类题的套路,就是设fi,ja序列的前i个数中长度为j的合法子序列有多少个。不难想到转移方程:

fi,j=fi1,j+fi1,j1×[aij==0]

但是这样时间复杂度就是O(nmax(ai)),严重超时,所以考虑优化。

因为第一维的i只和i1有关,而且j要是ai的因数,所以可以预处理出所有ai的因数,第二维只用遍历ai的因数就可以了。于是我们定义fi为造了长度恰好为i的⼦序列的⽅案数(跟a序列的长度无关),ysi,jai的第j个因数,则转移方程如下:

fysi,j=fysi,j+fysi,j1(ysai)

这样子时间复杂度就是O(nai),就可以过了。是不是很简单?

代码

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
vector<int> ys[100001];
int n,a[100001],f[1000001],ans=0;
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=sqrt(a[i]);j++){
			if(a[i]%j==0){
				ys[i].push_back(j);
				if(j*j!=a[i]) ys[i].push_back(a[i]/j);
			}
		}
	}
	f[0]=1;
	for(int i=1;i<=n;i++) {
		for(int j=ys[i].size()-1;j>=0;j--){
			f[ys[i][j]]=(f[ys[i][j]]+f[ys[i][j]-1])%mod;
			ans=(ans+f[ys[i][j]-1])%mod;
		}
	}
	printf("%d",ans);
	return 0;
}

不要忘记点个赞哦

完结撒花

本文作者:AFewSuns

本文链接:https://www.cnblogs.com/AFewSuns/p/12760581.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   AFewSuns  阅读(152)  评论(4编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起