题意:求长度为n的数列方案数,数列需满足两个条件:1.均为正整数。2.相邻两个数乘积不能超过m
思路:考虑dp。
设表示前i个点以j结尾的方案数,则有:
可以得出:
双指针+数论分块解决。把每个m/i相同的值抽象成一个点,共同转移即可。
此时设表示在以j结尾(在第j块的最小值)
变形后的dp方程:
从小块开始,另一指针从大块开始往前跳
#include<bits/stdc++.h>
#define int long long
using namespace std;const int mod = 1e9 + 7 , N = 110 , M = 1e5 + 10;int n,m,k,f[2][M],len[M],bel[M],cnt,now;
signed main(){cin>>n>>m;int l=1,r=0;while(l<=m){r=m/(m/l);++k;bel[k]=r;len[k]=(r-l+1);l=r+1;}for(int i=1;i<=k;i++) f[0][i]=len[i]+f[0][i-1];for(int p=1;p<n;p++){now^=1;int j=k;for(int i=1;i<=k;i++){while(bel[j]*bel[i]>m) j--;f[now][i]=(f[now][i-1]+f[now^1][j]*len[i])%mod;}} cout<<f[now][k];return 0;
}