CCF-CSP 202104-4 校门外的树dp+因子数集合

Posted nefu-ljw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF-CSP 202104-4 校门外的树dp+因子数集合相关的知识,希望对你有一定的参考价值。

题目链接

http://118.190.20.162/view.page?gpid=T125

思路

对于n=2的情况,假设障碍物位置分别是a[i]和a[j](i>j),即两个障碍物相邻,中间没有障碍物阻挡,区间长度为a[i]-a[j],容易想到 a n s = f ( a [ i ] − a [ j ] ) ans=f(a[i]-a[j]) ans=f(a[i]a[j]),其中 f ( x ) f(x) f(x)函数表示求 x x x的因子个数(注意,此处的因子包括1,但不包括 x x x自身)。

对于n>2,考虑 O ( n 2 ) O(n^2) O(n2)复杂度的dp,则有 d p [ i ] = ∑ j = 1 i − 1 d p [ j ] ∗ c a l c ( i , j ) , i > j dp[i]=\\sum_j=1^i-1 dp[j]*calc(i,j),i>j dp[i]=j=1i1dp[j]calc(i,j)i>j,那么 a n s = d p [ n ] ans=dp[n] ans=dp[n]
其中 c a l c ( i , j ) calc(i,j) calc(i,j)表示下标分别为i, j(i>j)的两个障碍物之间的方案数。这里由于两个障碍物之间可能还会有若干个障碍物的阻挡,它们把[j, i]分成了若干个小区间,那么在计算时要考虑去除掉中间这若干个小区间的所有因子:具体做法是,倒序枚举j,每次将当前区间长度的所有因子加入集合,同时计入方案数,那么下次枚举更长的区间时(这次是[j, i],下次是[j-1, i]),如果出现了之前集合中加入的因子,就不计入答案。简而言之,就是用一个set集合来维护[j,i]区间中所有出现过的因子。

由于a[i]最大到1e5,那么可以预处理1e5范围内每个数的所有因子(大概总共1e6个因子,跑一遍没问题)。

100分代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+10,M=1e5,mod=1e9+7;

vector<int>fac[M+10]; // 每个数的所有因子(包括1,不包括它自身)
void get_fac()
	for(int i=1;i<=M/2;i++)
		for(int j=2*i;j<=M;j+=i) // 2*i,...,k*i(<=M)
			fac[j].push_back(i);
		
	


int a[N];
ll dp[N];

unordered_set<int>s; // 比set速度快,因为它有去重,但没有排序
ll calc(int i,int j)
	int x=a[i]-a[j];
	ll ret=0;
	for(int it:fac[x]) // x的所有因子(包括1,不包括它自身)
		if(s.count(it)==0) // 之前集合中没有it这个因子,那么这次就可以取,但下次不能取(加入集合)
			ret++; // 这次可以取
			s.insert(it); // 下次不能取(加入集合)
		
	
	s.insert(x); // 将它自身加入集合(下次不能再取)
	return ret;


int main()
	ios::sync_with_stdio(false);
	get_fac();
	int n; cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	dp[1]=1;
	for(int i=2;i<=n;i++)
		s.clear();
		for(int j=i-1;j>=1;j--)
			dp[i]=(dp[i]+dp[j]*calc(i,j)%mod)%mod;
	
	printf("%lld\\n",dp[n]);
	return 0;

/*
2
1 10
ans: 2

11
0 10 20 30 40 50 60 70 80 90 100
ans: 256507
*/

坑点

想清楚维护因子数集合时要不要算上两个特殊的因子:1,数本身。这里记录方案数时算上1,不算数本身;但是1和数本身都要加入到集合中,因为下次的长区间不能再取这个数了,否则就会撞上中间的障碍物。

参考

https://www.cnblogs.com/lipoicyclic/p/15020078.html

以上是关于CCF-CSP 202104-4 校门外的树dp+因子数集合的主要内容,如果未能解决你的问题,请参考以下文章

CSP 202104-4 校门外的树 python 动态规划DP + 约数优化

CCF202104-4 校门外的树(100分)打表

校门外的树

一本通1537校门外的树

Vijos1448校门外的树 题解

校门外的树