ZOJ Monthly, March 2018 - H Happy Sequence

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;
}


猜你喜欢

转载自blog.csdn.net/b_r_e_a_d/article/details/79515944