[dp]牛牛与数组

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

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

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

输入描述:

输入两个整数n,k

1 ≤ n ≤ 10
1 ≤ k ≤ 100000

输出描述:

输出一个整数
示例1

输入

复制
2 2

输出

复制
3
示例2

输入

复制
9 1

输出

复制
1
示例3

输入

复制
3 3

输出

复制
15
示例4

输入

复制
2 1234

输出

1515011
 

题意:求一个长度为n的数组,满足用1-k的数组成前一个小于等于后一个或后一个不是前一个的倍数的条件有多少种,模1e9+7

思路:当前一个数小于等于后一个数时,即使后一个数是前一个数的倍数也是可以成立的(两个条件只需满足一个),但只有当前一个数大于后一个数且前一个数是后一个数的倍数时,此方案才不成立,注意到不成立的方案数条件更少,所以用总方案数减去不成立的方案数求解时更容易,故设dp[i][j]为当前长度为i的数组末尾是j的方案数,当数组长度为1时,k种数的方案数都为1种,当长度i大于等于2时,若要在末尾加入数j,则用i-1长度的数组从1到k的方案数之和减去i-1时大于j的j的倍数的方案数即使长度为i时末尾加入j的方案数,最后计算长度为n的数组从1到k的方案数之和即为答案,注意计算时要模1e9+7

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int amn=1e5,mod=1e9+7;
 5 int dp[15][amn];
 6 int main(){
 7     int n,k;
 8     ll s,s1,ans=0;
 9     ios::sync_with_stdio(0);
10     cin>>n>>k;
11     memset(dp,0,sizeof dp);
12     for(int i=1;i<=k;i++)dp[1][i]=1;
13     for(int i=2;i<=n;i++){
14         s=0;
15         for(int j=1;j<=k;j++)
16             s=(s+dp[i-1][j])%mod;
17         for(int j=1;j<=k;j++){
18             s1=0;
19             for(int l=j+j;l<=k;l+=j)
20                 s1=(s1+dp[i-1][l])%mod;
21             dp[i][j]+=(s-s1)%mod;
22         }
23         }
24     for(int j=1;j<=k;j++)ans+=dp[n][j],ans%=mod;
25     printf("%lld\n",ans);
26 }

猜你喜欢

转载自www.cnblogs.com/brainm/p/11285826.html