T^T ONLINE JUDGE 1593 翻倍序列
翻倍序列
TimeLimit:10000ms MemoryLimit:128000KB
64-bit integer IO format:%lld
已解决 | 点击收藏
Problem Description
满足序列中除了第一个数外每个数是它前一个数的倍数的序列被称为翻倍序列 现在要求满足如下条件的翻倍序列: 1.序列的所有元素是1~n的正整数 2.序列的长度是k 求满足这样的翻倍序列的数有几种。 由于答案能很大,输出答案MOD 1000000007(10^9+7)
Input
输入包括多组数据 每组数据是一行两个整数n,k。(1<=n,k<=2000)
Output
对于每个输入数据,输出一个整数表示答案
SampleInput
3 2
6 4
2 1
SampleOutput
5
39
2
【思路】:
这个题目有点毒,一开始我因为题意读错,做不出来,后来经过学长的解释题意,就懂了。翻倍序列指的是(x[i+1])/x[i]=k;k为一个常数。就对了。
开一个dp【i】【j】的数组
dp【i】【j】代表的是在i个长度下尾数为j的序列的数量
我先将dp【1】【j】(1《=j《=n)全部=1,在进行下一步
就是【i】【j】肯定由【i-1】【j】(1《=j《=n)转移过来,所以枚举状态就对了,但是这样的结果就是TLE ,那怎样才能ac呢?就是逆过来想下,
【i】【j】的状态肯定由j%z==0的条件转移,那么我枚举z,令z一开始=j,(1《=j《=n)
然后z+=j,更新每个值。这样的话,复杂度就由O(N3)->O(N2LOGN),就能AC了*
附上代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 2005;
const long long MOD = 1e9+7;
int dp[MAXN][MAXN];
int main()
{
// memset(dp,0,sizeof(dp));
for(int i=1;i<=MAXN;i++)
dp[1][i]=1;
for(int i=2;i<=MAXN;i++)
{
for(int j=1;j<=MAXN;j++)
{
for(int z=j;z<=MAXN;z+=j)
{
dp[i][z]=((dp[i][z]%MOD)+(dp[i-1][j]%MOD))%MOD;
}
}
}
int n,k;
while(~scanf("%d%d",&n,&k))
{int sum=0;
for(int i=1;i<=n;i++)
sum=((sum)%MOD+(dp[k][i])%MOD)%MOD;
printf("%d
",sum);
}
return 0;
}