题面
题意
给你一个n,坐标上有2n个点,间距为1,让你求出满足题意得方案数。
每两个点连接成一条线段,要求线段两两之间要么长度相等,要么一个线段被另一个线段包含
题解(找规律)
设ai表示,n=i 时有多少方案数
当n=1时,有1种情况,就是直接两个点连起来
当n=2时,有3种情况
先考虑存在包含,将最外的两个点连起来,这种情况下就递归回了a1,
然后再考虑不存在包含,每遇到一个点连一条线,发现可以 ; 每遇到两个点连一条线,发现可以,方案数+2;
当n=3时,6种情况
先考虑存在包含,将最外的两个点连起来,递归出a2 ; 将最外的点和倒数第二外的点连起来,递归出a1,
然后再考虑不存在包含,每遇到一个点连一条线,发现可以,每遇到两个点连一条线,发现不可以,每遇到3个点连一条线,发现可以,方案数+2;
当n=4时,有13种情况
先考虑存在包含,将最外的两个点连起来,递归出a3,将最外的点和倒数第二外的点连起来,递归出a2,将最外的点和倒数第三外的点连起来,将倒数第二外的点连起来,递归出a1
然后再考虑不存在包含,每遇到一个点连一条线,发现可以,每遇到两个点连一条线,发现可以,每遇到3个点连一条线,发现不可以,每遇到4个点连一条线,发现可以,方案数+3;
现在我们可以发现,an的值是由两部分组成的,一部分就是递归前面的部分a1+a2+a3+…+an-1,另一部分就是n的因子个数(包括本身)
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int mod = 998244353;
int n;
ll cnt[N];
ll arr[N]; //前n项包含
ll res[N];
int main() {
cin >> n;
//打表求因子 O(nlogn)
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j += i) {
cnt[j]++;
}
}
res[1] = 1, arr[1] = 1;
for (int i = 2; i <= n; i++) {
res[i] = (arr[i - 1] % mod + cnt[i] % mod) % mod;
arr[i] = (arr[i - 1] % mod + res[i]) % mod;
}
cout << res[n] << endl;
return 0;
}