http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5719
这道题很亏了,知道了题意之后就想到dp,但是有个地方一直没优化复杂度太高一直tle,足足卡了一个小时。
题意是给你两个数字n和m,n代表数据范围1~n,m代表长度为m的集合。集合内前面的数必定要是后面的数的因子。
先找出1~2000内所有数的因子,然后将结尾为1~2000的长度为1的集合值初始化为1。然后不断增加集合长度。
最后以O(1)效率输出结果。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int mod=1000000007;
int T;
int n,m;
int dp[2002][2002];
vector<int> fac[2002];
int main()
{
for(int i=1;i<=2000;i++)
{
for(int j=1;j<=sqrt(i*1.0);j++)
{
if(i%j==0)
{
fac[i].push_back(j);
if(j!=i/j)
fac[i].push_back(i/j);
}
}
}
memset(dp,0,sizeof(dp));
for(int i=0;i<=2000;i++)
dp[i][1]=1;
for(int i=2;i<=2000;i++)
{
for(int j=1;j<=2000;j++)
{
for(int k=0;k<fac[j].size();k++)
{
(dp[j][i]+=dp[fac[j].at(k)][i-1])%=mod;
}
}
}
for(int i=1;i<=2000;i++)
{
for(int j=2;j<=2000;j++)
{
(dp[j][i]+=dp[j-1][i])%=mod;
}
}
cin>>T;
while(T--)
{
cin>>n>>m;
cout<<dp[n][m]<<endl;
}
return 0;
}