zoj 4011 Happy Sequence(动态规划)

大致题意:

假如有一个数列a1,a2,a3,a4,a5....an。

如果对于每一个a[k],都有a[k+1]%a[k]==0.

那我们称这个数列为happy sequence。

现在给你两个数n和m,在保证每个happy sequence中的元素不大于n的情况下,求长度为m的happy sequence有多少个??

这道题用动态规划去做,首先找状态,我们设数组f[i][j]表示以i结尾且长度为j的happy sequence个数。

那么状态方程则为:

f[i][j]=sum(f[k][j-1]),k为i的所有因子

解释一下状态方程:

既然f[i][j]表示以i结尾且长度为j的happy sequence个数,那么在此类数列后面再加个i的倍数(i*k%i==0)也是一个happy sequence,所以以i结尾的长度为j的happy sequence个数为所有的以i的因子结尾的长度为j-1的happy sequence个数之和。

这道题还有一个注意点,也是我提交了7次还超时的原因,一直怀疑自己的方法是否错了、、、、、

题目里说n,m不大于2000,那我们预先都处理好了存在f数组里,以后就可以直接输出答案,不用一次一次的算了。。。。(我好笨)


代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
const int mod=1000000007;
int f[2005][2005];
vector<int>V[2005];
void init()
{
    memset(f,0,sizeof(f));

    for(int i=1; i<=2005; i++)V[i].clear();
    for(int i=1; i<=2005; i++)
    {
        for(int j=1; j<=2005; j++)
        {
            if(j%i==0)
            {
                V[j].push_back(i);
            }
        }
    }
    for(int i=1; i<=2005; i++)f[i][1]=1;
    for(int i=2; i<=2000; i++)
    {
        for(int j=1; j<=2000; j++)
        {
            for(int k=0; k<V[j].size(); k++)
            {
                f[j][i]=(f[j][i]%mod+f[V[j][k]][i-1]%mod)%mod;
            }
            f[j][i]%=mod;
        }
    }
}
int main()
{
    int t;
    init();//直接一次性都算出
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            int sum=0;
            for(int i=1; i<=n; i++)
            {
                sum=(sum+f[i][m])%mod;//将所有以不大于n的数结尾且长度为m的happy sequence个数加起来就是答案了
            }
            printf("%d\n",sum);
        }
    }

}


猜你喜欢

转载自blog.csdn.net/zyy_1998/article/details/79511442