Codeforces 1061C

本文介绍了一种高效算法,用于解决寻找整数序列中特定子序列的问题,即找到所有满足第i位数能整除i的子序列,并计算其数量。通过动态规划和预处理因子的方式,将复杂度降低到可接受范围内。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给一个序列,找一个子序列,使得子序列中第i位的数能整除i,问能找到多少个子序列。
dp[i][j] 表示前i个数取得长度为j的子序列的个数
则dp[i][j] = dp[i-1][j] + (dp[i-1][j-1] if( a[i] % j == 0))可知i只和i-1有关系,故可以滚动起来
又 n 范围是1e5, n^2肯定TLE,进一步思考可知只有当a[i] %j == 0 时才需要更新,所以可以先把a[i]的因子都找出来,然后跟新这些因子即可。

#include <bits/stdc++.h>
using namespace std;

const int mod = 1e9 + 7;
int n,a[101010],mam,dp[1010110],ans; //dp[i] 表示长度为i的子序列的个数
vector <int> fact[1010101];	
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	cin>>n;
	for(int i = 1;i<=n;i++)	{
		cin>>a[i]; 
		mam = max(mam,a[i]);
	}
	for(int i = 1;i<=mam;i++)
		for(int j = 1;j<=mam/i;j++)
			fact[i*j].push_back(i);
	for(int i = 1;i<=n;i++)
		sort(fact[a[i]].begin(),fact[a[i]].end());
	dp[0] = 1; 
	for(int i = 1;i<=n;i++){
		 for(int j =fact[a[i]].size()-1;j>=0;j--){ 
		 	int x = fact[a[i]][j];
			dp[x] += dp[x-1];
			dp[x] %= mod;
		} 
	}	
	for(int i = 1;i<=n;i++) 
		ans += dp[i],ans %= mod;
	cout<<ans;		
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值