牛客(牛牛与数组 )

链接: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

输出描述:

输出一个整数
示例1

输入

复制
2 2

输出

复制
3
示例2

输入

复制
9 1

输出

复制
1
示例3

输入

复制
3 3

输出

复制
15
示例4

输入

复制
2 1234

输出

复制
1515011

#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map> 
#include <math.h>
using namespace std;
typedef long long ll;
//c(n,k)*c(m,k)*k! 
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int maxn=1e5+10;
const int mod=1e9+7;
int dp[20][maxn];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        dp[1][i]=1;
    }
    for(int i=2;i<=n;i++){
        int sum=0;
        for(int j=1;j<=m;j++){
            sum=(sum+dp[i-1][j])%mod; 
        }
        for(int j=1;j<=m;j++){
            int sum1=0;
            for(int k=j+j;k<=m;k+=j){
                sum1=(sum1+dp[i-1][k])%mod;
            }
            dp[i][j]+=(sum-sum1)%mod;
        }
        
    }
    ll ans=0;
    for(int j=1;j<=m;j++){
        ans+=dp[n][j];
        ans%=mod;
    }
    printf("%lld",ans);
} 
/*
题意:求一个长度为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
*/

猜你喜欢

转载自www.cnblogs.com/lipu123/p/12920483.html
今日推荐