题目描述
X 校最近打算美化一下校园环境。
前段时间因为修地铁,X 校大门外种的行道树全部都被移走了。
现在 X 校打算重新再种一些树,为校园增添一抹绿意。
X 校大门外的道路是东西走向的,我们可以将其看成一条数轴。
在这条数轴上有 n 个障碍物,例如电线杆之类的。
虽然障碍物会影响树的生长,但是障碍物不一定能被随便移走,所以 X 校规定在障碍物的位置上不能种树。
n 个障碍物的坐标都是整数;如果规定向东为正方向,则 n 个障碍物的坐标按照从西到东的顺序分别为 a1,a2,⋯,an。
X 校打算在 [a1,an] 之间种一些树,使得这些树看起来比较美观。
X 校希望,在一定范围内,树应该是等间隔的。
更具体地说,如果把 [a1,an) 划分成一些区间 [ap1,ap2),⋯,[apm−1,apm)(1=p1<p2<⋯<pm=n),那么每个区间 [api,api+1) 内需要至少种一棵树,且该区间内种的树的坐标连同区间端点 api,api+1 应该构成一个等差数列。
不同区间的公差,也就是树的间隔可以不相同。
例如,如果障碍物位于 0,2,6 这三处,那么我们可以选择在 [0,2) 和 [2,6) 分别种树,也可以选择在 [0,6) 等间隔种树。
如果是分别在 [0,2) 和 [2,6) 种树,由于每个区间内至少要种一棵树,坐标 1 上必须种树;而 [2,6) 上的树可以按照 1 的间隔种下,也可以按照 2 的间隔种下。
下图表示了这两种美观的种树方案,其中橙色的圆表示障碍物,绿色的圆表示需要在这个位置种树,箭头上的数字表示种下这棵树时对应的间隔为多少。
对区间 [0,2) 和 [2,6) 分别以 1 和 2 的间隔种树是美观的
对区间 [0,2) 和 [2,6) 分别以 1 的间隔种树也是美观的
而如果选择在 [0,6) 区间等间隔种树,我们只能以 3 的间隔种树,因为无论是选择间隔 1 或者间隔 2,都需要在坐标 2 上种树,而这个位置已经有障碍物了。
下图分别表示了间隔为 3,2,1 时的种树情况,红色箭头表示不能在这里种树。
对区间 [0,6) 以 3 的间隔种树是美观的
.png)
对区间 [0,6) 以 2 的间隔种树是不美观的
对区间 [0,6) 以 1 的间隔种树也是不美观的
一般地,给定一个区间 [al,ar),对于树的坐标的集合 T⊂(al,ar)(T⊂Z),归纳定义 T 在 [al,ar) 上是美观的:
如果 T≠∅,T∩{al,al+1,⋯,ar}=∅,并且存在一个公差 d≥1,使得 T∪{al,ar} 中的元素按照从小到大的顺序排序后,可以构成一个公差为 d 的等差数列(显然,这个等差数列的首项为 al,末项为 ar),则 T 在 [al,ar) 上是美观的;
如果 T∩{al,al+1,⋯,ar}=∅,并且存在一个下标 m(l<m<r),使得 T∩(al,am) 在 [al,am) 上是美观的,且 T∩(am,ar) 在 [am,ar) 上是美观的,则 T 在 [al,ar) 上是美观的。
根据这一定义,空集在任意区间上都不是美观的;另外,如果存在下标 i 使得 ai∈T,那么 T 一定不是美观的。
我们称两种种树的方案是本质不同的,当且仅当两种方案中,种树的坐标集合不同。
请帮助 X 校对 [a1,an) 求出所有本质不同的美观的种树方案。
当然,由于方案可能很多,你只需要输出总方案数对 109+7 取模的结果。
输入格式
输入的第一行包含一个正整数 n,表示障碍物的数量。
输入的第二行包括 n 个非负整数 a1,⋯,an,表示每个障碍物的坐标。
保证对 i=1,2,⋯,n−1,ai<ai+1。
输出格式
输出一个非负整数,表示本质不同的美观的种树方案的数量对 109+7 取模的结果。
数据范围
对于 10% 的数据,保证 n=2;
对于 30% 的数据,保证 n≤10;
对于 60% 的数据,保证 n≤100,ai≤1000;
对于 100% 的数据,保证 2≤n≤1000,0≤ai≤100,000,且至少存在一种美观的种树方案。
样例
输入样例1:
3
0 2 6
输出样例1:
3
样例1解释
这组样例即为题面描述中提到的那组。
输入样例2:
11
0 10 20 30 40 50 60 70 80 90 100
输出样例2:
256507
输入样例3:
333
输出样例3:
33 44 67 210 528 762 873 984 1234 1466 1739 2859 3421 4061 4598 5172 5201 5220 5261 5322 5389 5559 6670 7070 7898
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N=1010,M=2e5+10,mod=1e9+7;
vector<int> cnt[M];
int n;
int a[N];
int f[N];
bool st[M];
void init(){ ///处理约数数组cnt
for(int i=1;i<M;i++){
for(int j=2*i;j<M;j+=i){
cnt[j].push_back(i);
}
}
}
int main(){
scanf("%d", &n);
for (int i = 0; i <n; i ++ ) scanf("%d",&a[i]);
init();
f[0]=1;
for(int i=1;i<n;i++){
memset(st,0,sizeof st);
for(int j=i-1;j>=0;j--){
int k=a[i]-a[j];
int num=0;
for(auto x:cnt[k]){
if(st[x]) continue;
st[x]=true;
num++;
}
st[k]=true;
f[i]=(f[i]+(long long)f[j]*num)%mod;
}
}
cout<<f[n-1];
return 0;
}
ni也mei换啊
破句!!!
很有意境
ljh,lpq,xyy,jyc,lyz
你tm的
总感觉怪怪的
怪就对了,他用我们班的几个人名组成的