牛牛与数组(DP)

链接:https://ac.nowcoder.com/acm/problem/21738来源:牛客网

题目描述

牛牛喜欢这样的数组:
1:长度为n
2:每一个数都在1到k之间
3:对于任意连续的两个数A,B,A<=B 与(A % B != 0) 两个条件至少成立一个

请问一共有多少满足条件的数组,对1e9+7取模

输入描述:

输入两个整数n,k

1 ≤ n ≤ 10
1 ≤ k ≤ 100000

输出描述:

输出一个整数

具体思路:

dp[i][j]表示前i个序列,第i个位j的时候的合法情况。

如果是三层暴力的话,肯定会T,我们可以记录第二个for循环的总值,然后再去把不符合的情况给去掉。如果条件1,我们累加这个数前面的数就好了。

对于条件2,我们先预处理出来每个数的倍数,然后再减去不合法的情况就可以了。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 # define inf 0x3f3f3f3f
 5 const int maxn = 2e5+100;
 6 const int  N = 15;
 7 const int mod = 1e9+7;
 8 ll dp[N][maxn];
 9 vector<ll>sto[maxn];
10 int main(){
11 int n,k;
12 scanf("%d %d",&n,&k);
13 for(int i=1;i<=k;i++){
14 dp[1][i]=1;
15 }
16 for(int i=1;i<=k;i++){
17 for(int j=2;j*i<=k;j++){
18 sto[i].push_back(i*j);
19 }
20 }
21 for(int i=2;i<=n;i++){
22 ll sum=0;
23 for(int j=1;j<=k;j++){sum=(sum+dp[i-1][j])%mod;}
24 ll tmp=0;
25 for(int j=1;j<=k;j++){
26 dp[i][j]=(dp[i-1][j]+tmp)%mod;
27 tmp=(tmp+dp[i-1][j])%mod;
28 ll ans=(sum-tmp+mod)%mod;// 把已经算过的情况给删除
29 for(int w=0;w<sto[j].size();w++){
30 ans=(ans-dp[i-1][sto[j][w]]+mod)%mod;
31 }
32 dp[i][j]=(dp[i][j]+ans)%mod;
33 }
34 }
35 ll ans=0;
36 for(int i=1;i<=k;i++){
37 ans=(ans+dp[n][i])%mod;
38 }
39 printf("%lld\n",ans);
40 return 0;
41 }

猜你喜欢

转载自www.cnblogs.com/letlifestop/p/10966724.html