牛客竞赛 21738 牛牛与数组(动态规划)

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

请问一共有多少满足条件的数组,对1e9+7取模
输入描述:
输入两个整数n,k

1 ≤ n ≤ 10
1 ≤ k ≤ 100000
输出描述:
输出一个整数

题意:
找出所有长度为n且满足任意连续的两个数A,B(数列中A的位置在B前面)A<=B或者A不是B的倍数。

题解:
今天看见牛客网讨论区有人问这道题目,恰好我曾经写过。故写下拙作一篇,望能对有需要的人提供一点点帮助!

此题可用动态规划求解,设立一个数组dp[i][j](dp[i][j]表示长度为i且尾数为j的数组个数(对1e9+7取模))
那么对于每一个dp[i][j]来说,数列的来源都是dp[i-1][x](x为1至j)来的。即为在符合题目条件下对长度为i-1的数列后端加上数字j作为其新的尾数。
直接找满足的数列个数很容易疏漏,但是很容易找到不满足题目条件的情况。所以我们可以利用数列总数减去不满足条件的个数即可得到答案。
满足A%B!=0,即表示A不是B的倍数即可,这个条件也包含了A<B,对于A==B,剔除时特判即可。
(也就是在剔除时,直接从2倍的B开始即可)
附上AC代码:

#include <iostream>
#include <vector>
using namespace std;
#define LL long long
const int mod =1e9+7;
int main()
{
    ios::sync_with_stdio(false);
    int n,k;
    LL ans=0;
    int dp[11][100001];//dp[i][j]表示长度为i且尾数为j的数组个数(对1e9+7取模)

    cin>>n>>k;
    for(int i=0;i<=k;i++)dp[1][i]=1;

    int sum,sum1;
    for(int i=2;i<=n;i++)
    {
        sum = 0;
        //长度为i-1的数列数目
        for(int j = 1; j <= k; j++)
        {
            sum += dp[i-1][j];
            sum %= mod;
        }
        
        for(int j = 1; j <= k; j++)
        {
            sum1 = 0;
            for(int x = j+j; x <= k; x+=j)
            {
                sum1 += dp[i-1][x];
                sum1 %= mod;
            }
            //长度为i尾数为j的数列数目 = 长度为i-1的所有 减去 长度为i-1尾数是j的倍数的
            dp[i][j] = (sum - sum1) % mod;//过程:相当于在长度为i-1的数列的后面加上一个数j的数组个数
        }

    }
    
    for(int i=1;i<=k;i++)
    {
        ans+=dp[n][i];
        ans%=mod;
    }
    cout<<ans<<endl;

    return 0;
}


若有什么地方有问题或者有看不懂的,欢迎指正和评论!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值